From 51bbf0eef2641d7766e22e188d6c349d9b836023 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Mon, 4 Sep 2017 19:20:45 +0300 Subject: [PATCH] fixed segfault on loading invalid maps --- src/game/g_gui.pas | 2 ++ src/game/g_map.pas | 10 +++++++++- src/shared/xdynrec.pas | 17 +++++++++++++++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/game/g_gui.pas b/src/game/g_gui.pas index 4f4a2c3..d59c838 100644 --- a/src/game/g_gui.pas +++ b/src/game/g_gui.pas @@ -2818,6 +2818,8 @@ begin FreeMem(Data); + if (map = nil) then exit; + try panlist := map.field['panel']; //header := GetMapHeader(map); diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 50b0d26..bbf39cb 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -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; diff --git a/src/shared/xdynrec.pas b/src/shared/xdynrec.pas index e1bd571..d82867e 100644 --- a/src/shared/xdynrec.pas +++ b/src/shared/xdynrec.pas @@ -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} -- 2.29.2