Page 1 of 1

cjson error handling

Posted: Mon Jul 09, 2018 6:31 pm
by ginodecock
Hi,

I am using the buildin cjson component to parse json data. When the data is not well formed the esp32 crashes:

Code: Select all

Guru Meditation Error: Core  0 panic'ed (LoadProhibited)
. Exception was unhandled.
Register dump:
PC      : 0x4010ad64  PS      : 0x00060e30  A0      : 0x8013e2fd  A1      : 0x3fff0510
0x4010ad64: cc_callback at C:/msys32/home/projects/sl_ulp_ijzer_templogger/main/cc_client.c:183

A2      : 0x4000beb8  A3      : 0x00000000  A4      : 0x0000005a  A5      : 0x00000000
A6      : 0x3ffdc558  A7      : 0x0000000c  A8      : 0x8010ad64  A9      : 0x3fff04f0
A10     : 0x00000000  A11     : 0x3f40ca12  A12     : 0x0000000a  A13     : 0x3ffdc6e4
A14     : 0x3ffdc6e4  A15     : 0x00000076  SAR     : 0x00000008  EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000014  LBEG    : 0x4000c46c  LEND    : 0x4000c477  LCOUNT  : 0x00000000

Backtrace: 0x4010ad64:0x3fff0510 0x4013e2fa:0x3fff0650 0x4010ac06:0x3fff0710 0x4010ad25:0x3fff42e0
0x4010ad64: cc_callback at C:/msys32/home/projects/sl_ulp_ijzer_templogger/main/cc_client.c:183

0x4013e2fa: req_process_download at C:/msys32/home/projects/sl_ulp_ijzer_templogger/components/esp-request/esp_request.c:710
 (inlined by) req_perform at C:/msys32/home/projects/sl_ulp_ijzer_templogger/components/esp-request/esp_request.c:680

0x4010ac06: cc_offload at C:/msys32/home/projects/sl_ulp_ijzer_templogger/main/cc_client.c:183

0x4010ad25: cc_https_task at C:/msys32/home/projects/sl_ulp_ijzer_templogger/main/cc_client.c:183

This is the code for the parsing:
int cc_callback(request_t *req, char *data, int len)

Code: Select all

{
	cJSON_Hooks memoryHook;

	memoryHook.malloc_fn = malloc;
	memoryHook.free_fn = free;
	cJSON_InitHooks(&memoryHook);
	struct timeval now;
	cJSON * root   = cJSON_Parse(data);
	cc_nextOffload = cJSON_GetObjectItem(root,"nextoffload")->valueint;
	cc_firmware = cJSON_GetObjectItem(root,"firmware")->valueint;
	cc_time = cJSON_GetObjectItem(root,"time")->valueint;
	cc_temphigh = cJSON_GetObjectItem(root,"temphigh")->valueint;
	cc_templow = cJSON_GetObjectItem(root,"templow")->valueint;
	cc_display = cJSON_GetObjectItem(root,"display")->valueint;
	char * rendered = cJSON_Print(root);
	ESP_LOGI(TAG,"%s\n", rendered);
	free(rendered);
	cJSON_Delete(root);
	ESP_LOGI(TAG,"nextOffload found nextOffload= %d",cc_nextOffload);
	ESP_LOGI(TAG,"Thermostat temperature high found tempHigh= %d",cc_temphigh);
	ESP_LOGI(TAG,"Thermostat temperature low found tempLow= %d",cc_templow);
	ESP_LOGI(TAG,"Display message to show= %d",cc_display);
       return 0;
}
I suppose the core reason of the crash is that cjson is not thread safe.
Please if someone knows best practice how to use cjson to parse safely?

Thanks,

Re: cjson error handling

Posted: Mon Jul 09, 2018 8:43 pm
by kolban
At which source line in your application is the failure occurring?

Re: cjson error handling

Posted: Tue Jul 10, 2018 1:14 am
by ESP_igrr
Based on the call stack, the error does not come from cjson. You may get more precise error indication if you enable GDBStub, but my guess would be that one of cJSON_GetObjectItem calls returns NULL, which you immediately dereference with ->valueint. Try checking the return value before dereferencing.

Re: cjson error handling

Posted: Tue Jul 10, 2018 10:46 am
by ginodecock
Hi,

@ESP_igrr your guess is right.
checking if the returns is NULL before dereferencing makes the json parsing robust.