Skip to content

Commit 46097f3

Browse files
committed
Implemented handling for dictionary start, list start and boolean value cases in string parser. String parser object stack is now deleted on every function return to avoid memory leak. Added some code simplifications in string parser function.
1 parent c59b06c commit 46097f3

File tree

1 file changed

+156
-31
lines changed

1 file changed

+156
-31
lines changed

src/cJSON.c

Lines changed: 156 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
117117
}
118118
else
119119
{
120-
// Skip invalid characters
120+
// Skip leading characters
121121
str++;
122122
continue;
123123
}
@@ -132,59 +132,119 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
132132
case '\t': // Ignore tab character
133133
case '\n': // Ignore newline character
134134
break;
135-
case '{':
136-
// Start dictionary
135+
case '{':;
136+
// Start dictionary, allocate generic dictionary object
137+
cJSON_Generic_t dictObj;
138+
dictObj = mallocGenObj(Dictionary);
139+
140+
// Check if start dictionary is possible
141+
if (pFlags & CJP_DICT_VALUE_POSSIBLE)
142+
{
143+
cJSON_appendToDict(AS_DICT_PTR(GS_TOP(ObjectStack)), activeKey, dictObj);
144+
}
145+
else if (pFlags & CJP_LIST_VALUE_POSSIBLE)
146+
{
147+
cJSON_appendToList(AS_LIST_PTR(GS_TOP(ObjectStack)), dictObj);
148+
}
149+
else
150+
{
151+
// Dictionary at invalid location in structure, delete object stack, delete generic dictionary object and return error
152+
GS_Delete(&ObjectStack);
153+
cJSON_delGenObj(dictObj);
154+
return cJSON_Structure_Error;
155+
}
156+
157+
// Push dictionary object to stack, check if JSON structure is within depth range
158+
if (GS_Push(&ObjectStack, dictObj) != GS_Ok)
159+
{
160+
// String's JSON structure depth is out of range, delete object stack and return error
161+
GS_Delete(&ObjectStack);
162+
return cJSON_DepthOutOfRange_Error;
163+
}
164+
165+
// Update flags
166+
pFlags = CJP_DICT_END_POSSIBLE | CJP_DICT_KEY_POSSIBLE;
137167
break;
138168
case '}':
139169
// Check if end dictionary is possible
140170
if (pFlags & CJP_DICT_END_POSSIBLE)
141171
{
142-
// End dictionary
172+
// End dictionary, remove generic dictionary object from stack
143173
GS_Pop(&ObjectStack);
144174

145175
if (GS_IS_EMPTY(ObjectStack))
146176
{
147177
// Clear parser flags, stack is empty, parsing complete, wait for string terminator
148178
pFlags = 0;
149179
}
180+
else if (GS_TOP(ObjectStack).type == Dictionary)
181+
{
182+
pFlags = CJP_DICT_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
183+
}
150184
else
151185
{
152-
if (GS_TOP(ObjectStack).type == Dictionary)
153-
{
154-
pFlags = CJP_DICT_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
155-
}
156-
else
157-
{
158-
pFlags = CJP_LIST_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
159-
}
186+
pFlags = CJP_LIST_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
160187
}
161188
}
189+
else
190+
{
191+
// Dictionary end at invalid location, delete object stack and return error
192+
GS_Delete(&ObjectStack);
193+
return cJSON_Structure_Error;
194+
}
162195
break;
163-
case '[':
164-
// Start list
196+
case '[':;
197+
// Start list, allocate generic list object
198+
cJSON_Generic_t listObj;
199+
listObj = mallocGenObj(List);
200+
201+
// Check if start list is possible
202+
if (pFlags & CJP_DICT_VALUE_POSSIBLE)
203+
{
204+
cJSON_appendToDict(AS_DICT_PTR(GS_TOP(ObjectStack)), activeKey, listObj);
205+
}
206+
else if (pFlags & CJP_LIST_VALUE_POSSIBLE)
207+
{
208+
cJSON_appendToList(AS_LIST_PTR(GS_TOP(ObjectStack)), listObj);
209+
}
210+
else
211+
{
212+
// List at invalid location in structure, delete object stack, delete generic list object and return error
213+
GS_Delete(&ObjectStack);
214+
cJSON_delGenObj(listObj);
215+
return cJSON_Structure_Error;
216+
}
217+
218+
// Push list object to stack, check if JSON structure is within depth range
219+
if (GS_Push(&ObjectStack, listObj) != GS_Ok)
220+
{
221+
// JSON structure depth is out of range, delete object stack and return error
222+
GS_Delete(&ObjectStack);
223+
return cJSON_DepthOutOfRange_Error;
224+
}
225+
226+
// Update flags
227+
pFlags = CJP_DICT_END_POSSIBLE | CJP_DICT_KEY_POSSIBLE;
165228
break;
166229
case ']':
167230
// Check if end list is possible
168231
if (pFlags & CJP_DICT_END_POSSIBLE)
169232
{
170-
// End list
233+
// End list, remove generic list object from stack
171234
GS_Pop(&ObjectStack);
172235

173236
if (GS_IS_EMPTY(ObjectStack))
174237
{
175238
// Clear parser flags, stack is empty, parsing complete, wait for string terminator
176239
pFlags = 0;
177240
}
241+
else if (GS_TOP(ObjectStack).type == Dictionary)
242+
{
243+
pFlags = CJP_DICT_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
244+
}
178245
else
179246
{
180-
if (GS_TOP(ObjectStack).type == Dictionary)
181-
{
182-
pFlags = CJP_DICT_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
183-
}
184-
else
185-
{
186-
pFlags = CJP_LIST_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
187-
}
247+
pFlags = CJP_LIST_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
188248
}
189249
}
190250
break;
@@ -200,7 +260,8 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
200260
}
201261
else
202262
{
203-
// Item separator at illegal location detected
263+
// Item separator at invalid location detected, delete object stack and return error
264+
GS_Delete(&ObjectStack);
204265
return cJSON_Structure_Error;
205266
}
206267
break;
@@ -213,7 +274,8 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
213274
}
214275
else
215276
{
216-
// Dictionary key-value separator at illegal location detected
277+
// Dictionary key-value separator at invalid location detected, delete object stack and return error
278+
GS_Delete(&ObjectStack);
217279
return cJSON_Structure_Error;
218280
}
219281
break;
@@ -252,12 +314,18 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
252314
}
253315
else
254316
{
317+
// String at invalid location detected, delete object stack and return error
318+
GS_Delete(&ObjectStack);
255319
return cJSON_Structure_Error;
256320
}
257321

258322
// Check if StringBuilder was successful
259323
if (strBuilderResult != cJSON_Ok)
324+
{
325+
// StringBuilder exited unsuccessfully, delete object stack and return error
326+
GS_Delete(&ObjectStack);
260327
return strBuilderResult;
328+
}
261329
break;
262330
case '-':
263331
case '0':
@@ -286,13 +354,67 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
286354
}
287355
else
288356
{
289-
// Number at invalid location in structure
357+
// Number at invalid location in structure, delete object stack and return error
358+
GS_Delete(&ObjectStack);
290359
return cJSON_Structure_Error;
291360
}
292361
break;
293-
case 't':
294-
case 'f':
362+
case 't':;
363+
case 'f':;
295364
// Check if boolean is possible
365+
bool boolVal;
366+
cJSON_Generic_t boolObj;
367+
368+
if ((LOWER_CASE_CHAR(*str) == 't')
369+
&& (LOWER_CASE_CHAR(*(str + 1)) == 'r')
370+
&& (LOWER_CASE_CHAR(*(str + 2)) == 'u')
371+
&& (LOWER_CASE_CHAR(*(str + 3)) == 'e'))
372+
{
373+
// Bool value is "true", skip "true" character sequence, store result
374+
str += 3;
375+
boolVal = true;
376+
}
377+
else if ((LOWER_CASE_CHAR(*str) == 'f')
378+
&& (LOWER_CASE_CHAR(*(str + 1)) == 'a')
379+
&& (LOWER_CASE_CHAR(*(str + 2)) == 'l')
380+
&& (LOWER_CASE_CHAR(*(str + 3)) == 's')
381+
&& (LOWER_CASE_CHAR(*(str + 4)) == 'e'))
382+
{
383+
// Bool value is "false", skip "false" character sequence, store result
384+
str += 4;
385+
boolVal = false;
386+
}
387+
else
388+
{
389+
// Invalid character sequence, delete object stack and return error
390+
GS_Delete(&ObjectStack);
391+
return cJSON_InvalidCharacterSequence_Error;
392+
}
393+
394+
// Create generic object from boolean
395+
boolObj = mallocGenObj(Boolean);
396+
AS_BOOL(boolObj) = boolVal;
397+
398+
// Valid character sequence
399+
if (pFlags & CJP_DICT_VALUE_POSSIBLE)
400+
{
401+
cJSON_appendToDict(AS_DICT_PTR(GS_TOP(ObjectStack)), activeKey, boolObj);
402+
403+
pFlags = CJP_DICT_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
404+
}
405+
else if (pFlags & CJP_LIST_VALUE_POSSIBLE)
406+
{
407+
cJSON_appendToList(AS_LIST_PTR(GS_TOP(ObjectStack)), boolObj);
408+
409+
pFlags = CJP_LIST_END_POSSIBLE | CJP_ITEM_SEPT_POSSIBLE;
410+
}
411+
else
412+
{
413+
// Boolean at invalid location in structure, delete object stack, delete generic bool object and return error
414+
GS_Delete(&ObjectStack);
415+
cJSON_delGenObj(boolObj);
416+
return cJSON_Structure_Error;
417+
}
296418
break;
297419
case 'n':
298420
// Extract null, check if whole string matches
@@ -317,18 +439,21 @@ cJSON_Result_t cJSON_parseStr(cJSON_Generic_t *GObjPtr, const char *str)
317439
}
318440
else
319441
{
320-
// Null at invalid location in structure
442+
// Null at invalid location in structure, delete object stack and return error
443+
GS_Delete(&ObjectStack);
321444
return cJSON_Structure_Error;
322445
}
323446
}
324447
else
325448
{
326-
// Invalid character sequence
449+
// Invalid character sequence, delete object stack and return error
450+
GS_Delete(&ObjectStack);
327451
return cJSON_InvalidCharacterSequence_Error;
328452
}
329453
break;
330454
default:
331-
// Unknown structural character
455+
// Unknown character at current location detected, delete object stack and return error
456+
GS_Delete(&ObjectStack);
332457
return cJSON_Structure_Error;
333458
}
334459
}

0 commit comments

Comments
 (0)