TJSONConnectorTests.CompilationFailure Memory/AV Fail, Use of Freed Object

Issue #9 resolved
Алек Невашедело created an issue

problem is in dwsJSONConnector.pas , method TJSONConnectorSymbol.CreateAssignExpr where there is a code

   if Result=nil then begin
      left.Free;
      right.Free;//this releases last reference, causing DEALLOCATION
   end;
end;

TJSONConnectorSymbol.CreateAssignExpr is called from dwsCompiler.TdwsCompiler.CreateAssign method

 Result:=TConnectorSymbol(leftTyp).CreateAssignExpr(FProg, scriptPos, FExec, left, right);//this is call to TJSONConnectorSymbol.CreateAssignExpr
                  if Result=nil then
                     IncompatibleTypes(scriptPos, CPE_AssignIncompatibleTypes,
                                       right.Typ, left.Typ);//right.Typ is DEALLOCATED object usage!
                                       //left variable also can possibly  be freed by the time

I opine this is just bad design, where a method releases object, which is not previously acquired, but it's too hard to refactor whole library now so

 var
    classOpSymbol : TClassOperatorSymbol;
    classOpExpr : TFuncExprBase;
    assignOpExpr : TAssignExpr;
    classSymbol : TClassSymbol;
    intfSymbol : TInterfaceSymbol;
-   leftTyp : TTypeSymbol;
+   leftTyp,rightTyp : TTypeSymbol;
 begin
    if (right<>nil) and (right.Typ<>nil) then begin

       case token of
          ttASSIGN : begin
             leftTyp:=left.Typ;
@@ -12458,16 +12458,20 @@
                      end;
                   end else begin
                      FMsgs.AddCompilerError(scriptPos, CPE_IncompatibleOperands);
                      Result:=TAssignExpr.Create(FProg, scriptPos, FExec, left, right); // keep going
                   end;
                end else if leftTyp is TConnectorSymbol then begin
+                  rightTyp:=right.Typ;
+                  rightTyp.IncRefCount();
+                  try
                   Result:=TConnectorSymbol(leftTyp).CreateAssignExpr(FProg, scriptPos, FExec, left, right);
                   if Result=nil then
                      IncompatibleTypes(scriptPos, CPE_AssignIncompatibleTypes,
-                                       right.Typ, left.Typ);
+                                       rightTyp, leftTyp);
+                  finally rightTyp.Free();   end;
                end else begin
                   if left.IsExternal then
                      Result:=TAssignExternalExpr.Create(FProg, scriptPos, FExec, left, right)
                   else Result:=TAssignExpr.Create(FProg, scriptPos, FExec, left, right);
                end;
             end;

Comments (3)

  1. Log in to comment