DEADSOFTWARE

fixed segfault on loading invalid maps
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Mon, 4 Sep 2017 16:20:45 +0000 (19:20 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Mon, 4 Sep 2017 18:01:07 +0000 (21:01 +0300)
src/game/g_gui.pas
src/game/g_map.pas
src/shared/xdynrec.pas

index 4f4a2c3b07f86eeb542b8383e6a6e2a4099ff703..d59c838557761d29290813f3c667d366ec248151 100644 (file)
@@ -2818,6 +2818,8 @@ begin
 
   FreeMem(Data);
 
+  if (map = nil) then exit;
+
   try
     panlist := map.field['panel'];
     //header := GetMapHeader(map);
index 50b0d2669ae576f4647c599664b6d7c38dc094d2..bbf39cb5efb7bad44613c76d9352e0cb2655b37b 100644 (file)
@@ -373,7 +373,7 @@ begin
       result := dfmapdef.parseMap(pr);
     except on e: Exception do
       begin
-        if (pr <> nil) then e_LogWritefln('ERROR at (%s,%s): %s', [pr.line, pr.col, e.message])
+        if (pr <> nil) then e_LogWritefln('ERROR at (%s,%s): %s', [pr.tokLine, pr.tokCol, e.message])
         else e_LogWritefln('ERROR: %s', [e.message]);
         pr.Free(); // will free `wst`
         result := nil;
@@ -1677,6 +1677,12 @@ begin
 
     FreeMem(Data);
 
+    if (mapReader = nil) then
+    begin
+      e_LogWritefln('invalid map file: ''%s''', [mapResName]);
+      exit;
+    end;
+
     generateExternalResourcesList(mapReader);
     mapTextureList := mapReader['texture'];
     // get all other lists here too
@@ -2224,6 +2230,8 @@ begin
 
   FreeMem(Data);
 
+  if (mapReader = nil) then exit;
+
   if (mapReader.Width > 0) and (mapReader.Height > 0) then
   begin
     Result.Name := mapReader.MapName;
index e1bd571235d2ba9be15abe8d1e8e1480df4d22a6..d82867e7d504dd34ad0d1a152a9ffe7a872069d6 100644 (file)
@@ -1597,6 +1597,8 @@ var
   tk: AnsiString;
   edim: AnsiChar;
 begin
+  if (pr.tokType = pr.TTEOF) then raise Exception.Create('field value expected');
+  if (pr.tokType = pr.TTSemi) then raise Exception.Create('extra semicolon');
   // if this field should contain struct, convert type and parse struct
   case mEBS of
     TEBS.TNone: begin end;
@@ -1867,7 +1869,14 @@ var
 begin
   if (mRec2Free <> nil) then
   begin
-    for rec in mRec2Free do if (rec <> self) then rec.Free();
+    for rec in mRec2Free do
+    begin
+      if (rec <> self) then
+      begin
+        //writeln('freeing: ', LongWord(rec));
+        rec.Free();
+      end;
+    end;
     mRec2Free.Free();
     mRec2Free := nil;
   end;
@@ -2694,13 +2703,17 @@ begin
 
     // fields
     {$IF DEFINED(D2D_DYNREC_PROFILER)}stt := curTimeMicro();{$ENDIF}
+    //writeln('0: <', mName, '.', pr.tokStr, '>');
     fld := field[pr.tokStr];
+    //writeln('1: <', mName, '.', pr.tokStr, '>');
     {$IF DEFINED(D2D_DYNREC_PROFILER)}profFieldSearching := curTimeMicro()-stt;{$ENDIF}
     if (fld <> nil) then
     begin
+      //writeln('2: <', mName, '.', pr.tokStr, '>');
       if fld.defined then raise Exception.Create(Format('duplicate field ''%s'' in record ''%s''', [fld.mName, mName]));
       if fld.internal then raise Exception.Create(Format('internal field ''%s'' in record ''%s''', [fld.mName, mName]));
-      pr.skipToken();
+      pr.skipToken(); // skip field name
+      //writeln('3: <', mName, '.', pr.tokStr, '>:', pr.tokType);
       {$IF DEFINED(D2D_DYNREC_PROFILER)}stt := curTimeMicro();{$ENDIF}
       fld.parseValue(pr);
       {$IF DEFINED(D2D_DYNREC_PROFILER)}profFieldValParsing := curTimeMicro()-stt;{$ENDIF}