RDKEMW-22210: Fix coverity issues on xdial - #211
Conversation
Reason for change: Fixing coverity reported issues. Test Procedure: Refer ticket. Risks: Low Priority: P1 version: minor Signed-off-by: balaji velmurugan <balaji_velmurugan@comcast.com>
There was a problem hiding this comment.
Pull request overview
This PR targets Coverity-reported issues in the xdial server implementation, primarily by adding NULL checks and tightening memory/resource handling in the REST and SSDP paths.
Changes:
- Add NULL-guarding around request payload logging and additional-data URL escaping in the libsoup 3.0 REST POST handler.
- Free an allocated handler path string in the libsoup 2.4 SSDP initialization path to address a resource leak.
- Add a NULL check around
gdial_app_state_to_string()usage when building the app state XML response.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| server/libsoup/3.0/gdial-rest.c | Adds Coverity-driven NULL checks and adjusts string initialization in response builder logic. |
| server/libsoup/2.4/gdial-ssdp.c | Frees dail_ssdp_handler after handler registration to address a reported leak. |
| server/gdial-app.c | Guards against NULL state string when creating the <state> XML node. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (3)
server/libsoup/3.0/gdial-rest.c:438
payload_stris guarded, but the log still usesrequest_body->lengtheven whenrequest_body->datais NULL. With%.*s, a non-zero length would cause an out-of-bounds read from the empty string (and potentially log unrelated memory). Compute the length only whenrequest_bodyandrequest_body->dataare present (otherwise use 0).
// coverity fix : FORWARD_NULL - check for NULL request_body->data before using in log
const char *payload_str = (request_body && request_body->data) ? request_body->data : "";
GDIAL_LOGERROR("Starting the app with payload %.*s", (int)request_body->length, payload_str);
server/libsoup/3.0/gdial-rest.c:503
additional_data_url_safecomes fromg_uri_escape_string(), which returns GLib-allocated memory intended to be released withg_free(). Usingfree()can be incorrect on builds where GLib's allocator differs from libc.
if (additional_data_url_safe) free(additional_data_url_safe);
server/libsoup/3.0/gdial-rest.c:469
request_bodyis treated as nullable in this function (e.g., the earlierif (request_body && request_body->data && request_body->length)), but laterrequest_body->datais accessed unconditionally when settingpayload. Ifrequest_bodyis NULL, this will crash before the subsequentif (payload && strlen(payload))guard runs.
// coverity fix : FORWARD_NULL - check for NULL before calling g_uri_escape_string
gchar *additional_data_url_safe = additional_data_url ? g_uri_escape_string(additional_data_url, NULL, FALSE) : NULL;
GDIAL_LOGINFO("additionalDataUrl = %s, %s", additional_data_url ? additional_data_url : "(null)", additional_data_url_safe ? additional_data_url_safe : "(null)");
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
Suppressed comments (3)
server/libsoup/3.0/gdial-rest.c:439
payload_lenis derived fromrequest_body->lengtheven whenrequest_body->datais NULL. In that casepayload_strbecomes "" but%.*swill still readpayload_lenbytes, which can read past the empty string and trigger undefined behavior. Makepayload_lenconditional onrequest_body->dataas well.
const char *payload_str = (request_body && request_body->data) ? request_body->data : "";
int payload_len = (request_body) ? (int)request_body->length : 0;
GDIAL_LOGERROR("Starting the app with payload %.*s", payload_len, payload_str);
server/libsoup/3.0/gdial-rest.c:505
additional_data_url_safeis allocated byg_uri_escape_string(), which should be released withg_free()(GLib allocator), notfree(). Usingfree()can break if GLib is built with a non-system allocator.
if (additional_data_url_safe) free(additional_data_url_safe);
server/gdial-app.c:536
- This change makes the
<state>element disappear entirely whengdial_app_state_to_string()returns NULL (eg,GDIAL_APP_STATE_MAX). Previously the XML always contained a<state>element (possibly empty). To avoid a response-shape change, always emit the element and fall back to an empty string when the state is unknown.
const gchar *state_str = gdial_app_state_to_string(state);
if (state_str) {
xmlNewChild(nservice, NULL, BAD_CAST "state", BAD_CAST state_str);
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (2)
server/libsoup/3.0/gdial-rest.c:505
additional_data_url_safeis allocated byg_uri_escape_string(), which should be released withg_free()rather thanfree()to match GLib's allocation API.
if (additional_data_url_safe) free(additional_data_url_safe);
server/libsoup/3.0/gdial-rest.c:438
payload_lenis computed fromrequest_body->lengtheven whenrequest_body->datais NULL, butpayload_strfalls back to an empty string in that case. Iflengthis non-zero whiledatais NULL,%.*swill read past the empty string buffer. Compute the length only whendatais non-NULL as well.
// coverity fix : FORWARD_NULL - check for NULL request_body before accessing length and data
const char *payload_str = (request_body && request_body->data) ? request_body->data : "";
int payload_len = (request_body) ? (int)request_body->length : 0;
GDIAL_LOGERROR("Starting the app with payload %.*s", payload_len, payload_str);
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (2)
server/libsoup/3.0/gdial-rest.c:506
g_uri_escape_string()returns memory that should be released withg_free(), notfree(). Usingfree()here can be an allocator mismatch if GLib is built with a non-default allocator.
start_error = gdial_app_start(app, payload_safe, query_str_safe, additional_data_url_safe, gdial_rest_server);
if (query_str_safe) g_free(query_str_safe);
if (payload_safe) g_free(payload_safe);
if (additional_data_url_safe) free(additional_data_url_safe);
if (additional_data_url) g_free(additional_data_url);
server/gdial-app.c:536
- The new comment refers to a "USE_AFTER_FREE" issue, but the code change is a NULL-check on the return value of
gdial_app_state_to_string(). This is misleading for future readers and for tracking Coverity findings.
// coverity fix : USE_AFTER_FREE - check for NULL before using state_str
const gchar *state_str = gdial_app_state_to_string(state);
if (state_str) {
xmlNewChild(nservice, NULL, BAD_CAST "state", BAD_CAST state_str);
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (2)
server/libsoup/3.0/gdial-rest.c:506
additional_data_url_safeis created byg_uri_escape_string()(GLib allocation) but is freed withfree(). This can cause an allocator mismatch; useg_free()for GLib-allocated strings.
start_error = gdial_app_start(app, payload_safe, query_str_safe, additional_data_url_safe, gdial_rest_server);
if (query_str_safe) g_free(query_str_safe);
if (payload_safe) g_free(payload_safe);
if (additional_data_url_safe) free(additional_data_url_safe);
if (additional_data_url) g_free(additional_data_url);
server/libsoup/3.0/gdial-rest.c:551
- In the error path,
appmay refer to an existing singleton instance returned bygdial_app_find_instance_by_name()(no ref added). Unref'ing it here can destroy a running app instance unexpectedly. Only unref if this function created the instance.
// coverity fix : DEADCODE - check app for NULL before calling g_object_unref
if (app) {
g_object_unref(app);
app = NULL;
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (3)
server/libsoup/3.0/gdial-rest.c:506
g_uri_escape_string()returns GLib-allocated memory and should be released withg_free(), notfree(). Mixing allocators can break when GLib is configured with a different allocator/vtable.
if (additional_data_url) g_free(additional_data_url);
}
/*
server/libsoup/3.0/gdial-rest.c:439
payload_lenis derived fromrequest_body->lengtheven whenrequest_body->datais NULL, which can make%.*sread pastpayload_str(""), leading to out-of-bounds reads if libsoup ever provides a body with NULL data. Tie the length to the same condition used forpayload_str.
const char *payload_str = (request_body && request_body->data) ? request_body->data : "";
int payload_len = (request_body) ? (int)request_body->length : 0;
GDIAL_LOGERROR("Starting the app with payload %.*s", payload_len, payload_str);
GDialApp *app = gdial_app_find_instance_by_name(app_registry->name);
build_dependencies.sh:9
- Unquoted variable expansion can break if
$GITHUB_WORKSPACEever contains spaces or glob characters (word splitting / pathname expansion). Quote the variable when passing it to commands.
ls -la ${GITHUB_WORKSPACE}
cd ${GITHUB_WORKSPACE}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (2)
server/libsoup/3.0/gdial-rest.c:438
payload_lenis derived fromrequest_body->lengtheven whenrequest_body->datais NULL; in that casepayload_strbecomes "" and%.*swill read past the end of the empty string (undefined/out-of-bounds read). Tie the length to the same condition as the pointer.
const char *payload_str = (request_body && request_body->data) ? request_body->data : "";
int payload_len = (request_body) ? (int)request_body->length : 0;
GDIAL_LOGERROR("Starting the app with payload %.*s", payload_len, payload_str);
server/libsoup/3.0/gdial-rest.c:502
additional_data_url_safeis returned byg_uri_escape_string(), which is documented to be freed withg_free(). Usingfree()here can cause alloc/free mismatches if GLib uses a different allocator.
if (additional_data_url_safe) free(additional_data_url_safe);
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (3)
server/libsoup/3.0/gdial-rest.c:502
additional_data_url_safeis allocated byg_uri_escape_string()(GLib allocator) but freed withfree(). Mixing alloc/free families can cause invalid frees depending on the GLib build/allocator. Useg_free()for memory returned by GLib APIs.
if (additional_data_url_safe) free(additional_data_url_safe);
server/libsoup/3.0/gdial-rest.c:438
payload_lenis derived fromrequest_body->lengtheven whenrequest_body->datais NULL, whilepayload_strfalls back to "". Iflength > 0with NULL data (possible when no body is loaded/parsed),%.*swill read past the end of the empty string buffer and can crash or log garbage. Tie the length to the presence ofdata(or set both to 0/NULL together).
const char *payload_str = (request_body && request_body->data) ? request_body->data : "";
int payload_len = (request_body) ? (int)request_body->length : 0;
GDIAL_LOGERROR("Starting the app with payload %.*s", payload_len, payload_str);
server/gdial-app.c:535
- When
stateisGDIAL_APP_STATE_MAX(or any unexpected value),gdial_app_state_to_string()returns NULL. The new code omits the<state>element entirely in that case, which can break clients expecting the element to always exist. Prefer emitting<state>with an empty/fallback value rather than skipping the node.
const gchar *state_str = gdial_app_state_to_string(state);
if (state_str) {
xmlNewChild(nservice, NULL, BAD_CAST "state", BAD_CAST state_str);
}
Reason for change: Fixing coverity reported issues.
Test Procedure: Refer ticket.
Risks: Low
Priority: P1
version: minor