Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | fixed potential buffer overflow in TJSONObjectDecoder.EncodeAsSQLPrepared() |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
79f5becba890b73024302cf5eaca28d4 |
User & Date: | User 2013-12-07 20:05:42 |
2013-12-08
| ||
13:08 | do not reallocate dynamic array memory for smallest size (<=64 items) check-in: 1a8d821f4c user: User tags: trunk | |
2013-12-07
| ||
20:05 | fixed potential buffer overflow in TJSONObjectDecoder.EncodeAsSQLPrepared() check-in: 79f5becba8 user: User tags: trunk | |
2013-12-06
| ||
16:26 | renamed FieldNameValid() function into PropNameValid() for better consistency check-in: 4e22df67b6 user: abouchez tags: trunk | |
Changes to SQLite3/mORMot.pas.
766 767 768 769 770 771 772 773 774 775 776 777 778 779 .... 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 ..... 16698 16699 16700 16701 16702 16703 16704 16705 16706 16707 16708 16709 16710 16711 16712 16713 16714 16715 16716 16717 16718 16719 16720 16721 16722 16723 16724 16725 16726 16727 16728 16729 16730 16731 16732 16733 ..... 16735 16736 16737 16738 16739 16740 16741 16742 16743 16744 16745 16746 16747 16748 16749 ..... 16755 16756 16757 16758 16759 16760 16761 16762 16763 16764 16765 16766 16767 16768 16769 ..... 16803 16804 16805 16806 16807 16808 16809 16810 16811 16812 16813 16814 16815 16816 16817 ..... 16851 16852 16853 16854 16855 16856 16857 16858 16859 16860 16861 16862 16863 16864 16865 16866 |
/ ObjectToJSON() functions and WriteObject method - added TTypeInfo.ClassCreate() method to create a TObject instance from RTTI - TEnumType.GetEnumNameValue() will now recognize both 'sllWarning' and 'Warning' text as a sllWarning item (will enhance JSONToObject() process) - fix and enhance boolean values parsing from JSON content ("Yes"=true) - implement woHumanReadableFullSetsAsStar and woHumanReadableEnumSetAsComment option for JSON serialization and TEnumType.GetEnumNameTrimedAll() - added ClassInstanceCreate() function calling any known virtual constructor - added GetInterfaceFromEntry() function to speed up interface execution, e.g. for TServiceFactoryServer (avoid the RTTI lookup of GetInterface) - added TPropInfo.ClassFromJSON() to properly unserialize TObject properties - added TSQLPropInfo.SQLFieldTypeName property - fixed [f96cf0fc5d] and [221ee9c767] about TSQLRecordMany JSON serialization - fixed issue when retrieving a TSQLRecord containing TSQLRecordMany ................................................................................ /// contains the decoded field names or value FieldNames, FieldValues: array[0..MAX_SQLFIELDS-1] of RawUTF8; /// Decode() will set a bit for each field set JSON null value FieldNull: TSQLFieldBits; /// number of fields decoded in FieldNames[] and FieldValues[] FieldCount: integer; /// size of the TEXT data (in bytes) in FieldValues[] FieldLen: integer; /// set to TRUE if parameters are to be :(...): inlined InlinedParams: boolean; /// internal pointer over field names to be used after Decode() call // - either FieldNames, either Fields[] array as defined in Decode() DecodedFieldNames: PRawUTF8Array; /// the ID=.. value as sent within the JSON object supplied to Decode() DecodedRowID: integer; ................................................................................ end; end else // non string params (numeric or null/false/true) are passed untouched FieldValues[ndx] := res; end; end; end; Inc(FieldLen,length(FieldValues[ndx])); end; var FieldName: RawUTF8; F: integer; FieldIsRowID: Boolean; begin FieldCount := 0; FieldLen := 0; DecodedRowID := 0; FillChar(FieldNull,sizeof(FieldNull),0); InlinedParams := Params=pInlined; if pointer(Fields)=nil then begin // get "COL1"="VAL1" pairs, stopping at '}' or ']' DecodedFieldNames := @FieldNames; if RowID>0 then begin // insert explicit RowID if ReplaceRowIDWithID then FieldNames[0] := 'ID' else FieldNames[0] := 'RowID'; FieldValues[0] := Int32ToUtf8(RowID); FieldCount := 1; FieldLen := Length(FieldNames[0])+Length(FieldValues[0]); DecodedRowID := RowID; end; if P<>nil then repeat FieldName := GetJSONField(P,P); if P=nil then break; // syntax error FieldIsRowID := IsRowId(pointer(FieldName)); ................................................................................ if RowID>0 then begin GetJSONField(P,P,nil,@EndOfObject); // ignore this if explicit RowID if EndOfObject in [#0,'}',']'] then break else continue; end else if ReplaceRowIDWithID then FieldName := 'ID'; inc(FieldLen,length(FieldName)); FieldNames[FieldCount] := FieldName; GetSQLValue(FieldCount); // update EndOfObject if FieldIsRowID then DecodedRowID := GetInteger(pointer(FieldValues[FieldCount])); inc(FieldCount); if FieldCount=MAX_SQLFIELDS then raise EParsingException.Create('Too many inlines in GetJSONObjectAsSQL'); ................................................................................ if RowID>0 then raise EParsingException.Create('GetJSONObjectAsSQL(expanded) won''t handle RowID'); if length(Fields)>MAX_SQLFIELDS then raise EParsingException.Create('Too many inlines in GetJSONObjectAsSQL'); DecodedFieldNames := pointer(Fields); FieldCount := length(Fields); for F := 0 to FieldCount-1 do begin inc(FieldLen,length(Fields[F])); GetSQLValue(F); // update EndOfObject end; end; end; procedure TJSONObjectDecoder.Decode(JSON: RawUTF8; const Fields: TRawUTF8DynArray; Params: TJSONObjectDecoderParams; RowID: Integer=0; ReplaceRowIDWithID: Boolean=false); ................................................................................ 'insert into %%', 'update % set % where ID=?'); var F: integer; P: PUTF8Char; tmp: RawUTF8; begin result := ''; if FieldCount<>0 then begin SetLength(tmp,FieldLen+2*FieldCount+12); // max length P := pointer(tmp); case Occasion of soUpdate: begin // returns 'COL1=?,COL2=?' (UPDATE SET format) for F := 0 to FieldCount-1 do begin P := AppendRawUTF8ToBuffer(P,DecodedFieldNames[F]); PInteger(P)^ := Ord('=')+Ord('?')shl 8+Ord(',')shl 16; ................................................................................ var F, Len: integer; P: PUTF8Char; begin result := ''; if FieldCount=0 then exit; if InlinedParams then Len := FieldLen+6*FieldCount else Len := FieldLen+2*FieldCount; if Update then begin // returns 'COL1='VAL1',COL2=VAL2' (UPDATE SET format) SetLength(result,Len-1); // -1 for last ',' P := pointer(result); for F := 0 to FieldCount-1 do begin P := AppendRawUTF8ToBuffer(P,DecodedFieldNames[F]); if InlinedParams then begin |
> | > > | | > | > | | | | | |
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 .... 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 ..... 16701 16702 16703 16704 16705 16706 16707 16708 16709 16710 16711 16712 16713 16714 16715 16716 16717 16718 16719 16720 16721 16722 16723 16724 16725 16726 16727 16728 16729 16730 16731 16732 16733 16734 16735 16736 16737 16738 ..... 16740 16741 16742 16743 16744 16745 16746 16747 16748 16749 16750 16751 16752 16753 16754 ..... 16760 16761 16762 16763 16764 16765 16766 16767 16768 16769 16770 16771 16772 16773 16774 ..... 16808 16809 16810 16811 16812 16813 16814 16815 16816 16817 16818 16819 16820 16821 16822 ..... 16856 16857 16858 16859 16860 16861 16862 16863 16864 16865 16866 16867 16868 16869 16870 16871 |
/ ObjectToJSON() functions and WriteObject method - added TTypeInfo.ClassCreate() method to create a TObject instance from RTTI - TEnumType.GetEnumNameValue() will now recognize both 'sllWarning' and 'Warning' text as a sllWarning item (will enhance JSONToObject() process) - fix and enhance boolean values parsing from JSON content ("Yes"=true) - implement woHumanReadableFullSetsAsStar and woHumanReadableEnumSetAsComment option for JSON serialization and TEnumType.GetEnumNameTrimedAll() - fixed potential buffer overflow in TJSONObjectDecoder.EncodeAsSQLPrepared() - added ClassInstanceCreate() function calling any known virtual constructor - added GetInterfaceFromEntry() function to speed up interface execution, e.g. for TServiceFactoryServer (avoid the RTTI lookup of GetInterface) - added TPropInfo.ClassFromJSON() to properly unserialize TObject properties - added TSQLPropInfo.SQLFieldTypeName property - fixed [f96cf0fc5d] and [221ee9c767] about TSQLRecordMany JSON serialization - fixed issue when retrieving a TSQLRecord containing TSQLRecordMany ................................................................................ /// contains the decoded field names or value FieldNames, FieldValues: array[0..MAX_SQLFIELDS-1] of RawUTF8; /// Decode() will set a bit for each field set JSON null value FieldNull: TSQLFieldBits; /// number of fields decoded in FieldNames[] and FieldValues[] FieldCount: integer; /// size of the TEXT data (in bytes) in FieldValues[] FieldValueLen: integer; /// size of the TEXT data (in bytes) in FieldNames[] FieldNameLen: integer; /// set to TRUE if parameters are to be :(...): inlined InlinedParams: boolean; /// internal pointer over field names to be used after Decode() call // - either FieldNames, either Fields[] array as defined in Decode() DecodedFieldNames: PRawUTF8Array; /// the ID=.. value as sent within the JSON object supplied to Decode() DecodedRowID: integer; ................................................................................ end; end else // non string params (numeric or null/false/true) are passed untouched FieldValues[ndx] := res; end; end; end; Inc(FieldValueLen,length(FieldValues[ndx])); end; var FieldName: RawUTF8; F: integer; FieldIsRowID: Boolean; begin FieldCount := 0; FieldValueLen := 0; FieldNameLen := 0; DecodedRowID := 0; FillChar(FieldNull,sizeof(FieldNull),0); InlinedParams := Params=pInlined; if pointer(Fields)=nil then begin // get "COL1"="VAL1" pairs, stopping at '}' or ']' DecodedFieldNames := @FieldNames; if RowID>0 then begin // insert explicit RowID if ReplaceRowIDWithID then FieldNames[0] := 'ID' else FieldNames[0] := 'RowID'; FieldValues[0] := Int32ToUtf8(RowID); FieldCount := 1; FieldNameLen := Length(FieldNames[0]); FieldValueLen := Length(FieldValues[0]); DecodedRowID := RowID; end; if P<>nil then repeat FieldName := GetJSONField(P,P); if P=nil then break; // syntax error FieldIsRowID := IsRowId(pointer(FieldName)); ................................................................................ if RowID>0 then begin GetJSONField(P,P,nil,@EndOfObject); // ignore this if explicit RowID if EndOfObject in [#0,'}',']'] then break else continue; end else if ReplaceRowIDWithID then FieldName := 'ID'; inc(FieldNameLen,length(FieldName)); FieldNames[FieldCount] := FieldName; GetSQLValue(FieldCount); // update EndOfObject if FieldIsRowID then DecodedRowID := GetInteger(pointer(FieldValues[FieldCount])); inc(FieldCount); if FieldCount=MAX_SQLFIELDS then raise EParsingException.Create('Too many inlines in GetJSONObjectAsSQL'); ................................................................................ if RowID>0 then raise EParsingException.Create('GetJSONObjectAsSQL(expanded) won''t handle RowID'); if length(Fields)>MAX_SQLFIELDS then raise EParsingException.Create('Too many inlines in GetJSONObjectAsSQL'); DecodedFieldNames := pointer(Fields); FieldCount := length(Fields); for F := 0 to FieldCount-1 do begin inc(FieldNameLen,length(Fields[F])); GetSQLValue(F); // update EndOfObject end; end; end; procedure TJSONObjectDecoder.Decode(JSON: RawUTF8; const Fields: TRawUTF8DynArray; Params: TJSONObjectDecoderParams; RowID: Integer=0; ReplaceRowIDWithID: Boolean=false); ................................................................................ 'insert into %%', 'update % set % where ID=?'); var F: integer; P: PUTF8Char; tmp: RawUTF8; begin result := ''; if FieldCount<>0 then begin SetLength(tmp,FieldNameLen+3*FieldCount+12); // max length P := pointer(tmp); case Occasion of soUpdate: begin // returns 'COL1=?,COL2=?' (UPDATE SET format) for F := 0 to FieldCount-1 do begin P := AppendRawUTF8ToBuffer(P,DecodedFieldNames[F]); PInteger(P)^ := Ord('=')+Ord('?')shl 8+Ord(',')shl 16; ................................................................................ var F, Len: integer; P: PUTF8Char; begin result := ''; if FieldCount=0 then exit; if InlinedParams then Len := FieldNameLen+FieldValueLen+6*FieldCount else Len := FieldNameLen+FieldValueLen+2*FieldCount; if Update then begin // returns 'COL1='VAL1',COL2=VAL2' (UPDATE SET format) SetLength(result,Len-1); // -1 for last ',' P := pointer(result); for F := 0 to FieldCount-1 do begin P := AppendRawUTF8ToBuffer(P,DecodedFieldNames[F]); if InlinedParams then begin |