I'm developing a tizen web app and to implement some background actions I'm using a native service along. The service executes fine for some time and after that, it crashes often when some memory allocated with malloc is freed using free.
Log cat is as follows:
07-13 19:44:54.529+0900 W/AUL ( 2463): app_signal.c: aul_send_app_launch_request_signal(521) > aul_send_app_launch_request_signal app(org.example.emedicalbtleservice) pid(7630) type(svcapp) bg(0)
07-13 19:44:54.529+0900 W/AUL ( 7629): launch.c: app_request_to_launchpad(298) > request cmd(0) result(7630)
07-13 19:44:54.539+0900 W/STARTER ( 2654): pkg-monitor.c: _app_mgr_status_cb(395) > [_app_mgr_status_cb:395] Launch request [7630]
07-13 19:44:54.569+0900 W/AUL_AMD ( 2463): amd_request.c: __request_handler(669) > __request_handler: 14
07-13 19:44:54.579+0900 W/AUL_AMD ( 2463): amd_request.c: __send_result_to_client(91) > __send_result_to_client, pid: 7630
07-13 19:44:54.579+0900 W/AUL_AMD ( 2463): amd_request.c: __request_handler(669) > __request_handler: 14
07-13 19:44:54.599+0900 W/AUL_AMD ( 2463): amd_request.c: __send_result_to_client(91) > __send_result_to_client, pid: 7630
07-13 19:44:54.599+0900 W/AUL_AMD ( 2463): amd_status.c: __socket_monitor_cb(1277) > (7630) was created
07-13 19:44:54.599+0900 W/AUL_AMD ( 2463): amd_request.c: __request_handler(669) > __request_handler: 12
07-13 19:44:54.599+0900 W/AUL_AMD ( 2463): amd_request.c: __request_handler(669) > __request_handler: 12
07-13 19:44:54.729+0900 E/PKGMGR_SERVER( 7542): pkgmgr-server.c: exit_server(1619) > exit_server Start [backend_status=1, queue_status=1]
07-13 19:44:54.729+0900 E/PKGMGR_SERVER( 7542): pkgmgr-server.c: main(2295) > package manager server terminated.
07-13 19:44:54.799+0900 I/emedicalbtleservice( 7630): /opt/usr/media
07-13 19:44:54.799+0900 I/emedicalbtleservice( 7630): /opt/usr/media/eMedicalBP.txt
07-13 19:44:54.989+0900 W/AUL ( 7638): daemon-manager-release-agent.c: main(12) > release agent : [2:/org.example.emedicalbtleservice]
07-13 19:44:54.989+0900 W/AUL_AMD ( 2463): amd_request.c: __request_handler(669) > __request_handler: 23
07-13 19:44:54.989+0900 W/AUL_AMD ( 2463): amd_request.c: __send_result_to_client(91) > __send_result_to_client, pid: 0
07-13 19:44:54.989+0900 W/AUL_AMD ( 2463): amd_request.c: __request_handler(1032) > pkg_status: installed, dead pid: 7630
07-13 19:44:54.989+0900 W/AUL_AMD ( 2463): amd_request.c: __send_app_termination_signal(528) > send dead signal done
07-13 19:44:55.009+0900 I/AUL_AMD ( 2463): amd_main.c: __app_dead_handler(262) > __app_dead_handler, pid: 7630
07-13 19:44:55.009+0900 W/AUL ( 2463): app_signal.c: aul_send_app_terminated_signal(799) > aul_send_app_terminated_signal pid(7630)
07-13 19:44:55.009+0900 W/CRASH_MANAGER( 7637): worker.c: worker_job(1205) > 0607630656d65149994269
Code snippet:
char* read_file(const char* filepath)
{
FILE *fp = fopen(filepath, "r");
if (fp == NULL)
{
dlog_print(DLOG_ERROR, LOG_TAG, "Cannot open file");
return NULL;
}
fseek(fp, 0, SEEK_END);
int bufsize = ftell(fp);
rewind(fp);
if (bufsize < 1)
{
dlog_print(DLOG_ERROR, LOG_TAG, "Cannot open file");
return NULL;
}
char *buf = malloc(sizeof(char) * (bufsize));
memset(buf, '\0', sizeof(buf));
char str[200];
while(fgets(str, 200, fp) != NULL)
{
sprintf(buf + strlen(buf), "%s", str);
}
fclose(fp);
return buf;
}
void get_password(char *filePath, int *password, bool *has_password)
{
char *fileContent = read_file(filePath); //charater pointer pointed to data read from file and memory allocated with malloc
if (fileContent == NULL)
{
*has_password = false;
dlog_print(DLOG_ERROR, LOG_TAG, "Do not have password");
return;
}
else
{
cJSON *root = cJSON_Parse(fileContent);
free(fileContent);
if (root != NULL && cJSON_IsObject(root))
{
cJSON *passwordArray = cJSON_DetachItemFromObjectCaseSensitive(root, "passwordArray");
cJSON_Delete(root);
root = NULL;
if (cJSON_IsArray(passwordArray))
{
for (int i = 0; i < cJSON_GetArraySize(passwordArray); ++i)
{
password[i] = cJSON_GetArrayItem(passwordArray, i)->valueint;
}
dlog_print(DLOG_INFO, LOG_TAG, "Has password");
*has_password = true;
}
else
{
dlog_print(DLOG_ERROR, LOG_TAG, "Password is not array");
*has_password = false;
}
cJSON_Delete(passwordArray);
}
else
{
dlog_print(DLOG_ERROR, LOG_TAG, "Content cannot be parsed");
*has_password = false;
}
if (root != NULL)
{
cJSON_Delete(root);
}
}
}
I'm using CJSON library to parse some JSON content stored in file. The service often crashes after it executes free(fileContent);
or cJSON_Delete(root);
In read_file
, you allocate space for buf
based on the file size, but you do not account for the null terminator written by sprintf
, so you have a buffer overflow which can cause heap corruption. (You could directly read into the buffer using fgets
, too.)