Skip to content

fix(cloud_proxy): harden parsing and async proxy error handling#665

Open
jkralik wants to merge 3 commits intomasterfrom
jkralik/fix/cloud-proxy-hardening
Open

fix(cloud_proxy): harden parsing and async proxy error handling#665
jkralik wants to merge 3 commits intomasterfrom
jkralik/fix/cloud-proxy-hardening

Conversation

@jkralik
Copy link
Copy Markdown
Member

@jkralik jkralik commented Apr 9, 2026

  • Prevent overflow when building discovered resource path by validating combined UDN and URI length before copy.
  • Validate anchor and URL formats before extracting UDN/local URI, and reject malformed inputs safely.
  • Add bounds checks for delayed response payload copies based on separate-response buffer limits.
  • Add null checks for delayed response allocations and handle dispatch/init failures for GET/POST/DELETE with explicit error responses and cleanup.
  • Fix delayed response lifetime for DELETE callback to avoid leaks.
  • Harden d2dserverlist DI handling with length validation, exact-length matching, and safe copy with explicit null termination.
  • Avoid incorrect rediscovery on already-known DI by tracking newly added entries before issuing discovery.
  • Replace unsafe deviceuuid query concatenation with bounded formatting and overflow check.

- Prevent overflow when building discovered resource path by validating combined UDN and URI length before copy.
- Validate anchor and URL formats before extracting UDN/local URI, and reject malformed inputs safely.
- Add bounds checks for delayed response payload copies based on separate-response buffer limits.
- Add null checks for delayed response allocations and handle dispatch/init failures for GET/POST/DELETE with explicit error responses and cleanup.
- Fix delayed response lifetime for DELETE callback to avoid leaks.
- Harden d2dserverlist DI handling with length validation, exact-length matching, and safe copy with explicit null termination.
- Avoid incorrect rediscovery on already-known DI by tracking newly added entries before issuing discovery.
- Replace unsafe deviceuuid query concatenation with bounded formatting and overflow check.
Copilot AI review requested due to automatic review settings April 9, 2026 18:29
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Walkthrough

Hardened cloud proxy parsing, D2D device handling, separate-response buffering, proxied resource operations, and discovery flows with input validation, explicit length handling, safer copying, and added error-return signaling; small test headers/enum comparison fixes added.

Changes

Cohort / File(s) Summary
Cloud proxy core
apps/cloud_proxy.c
Major hardening: NULL/input validation, explicit length checks, replace unsafe strcpy/strcat/strncpy with memcpy/snprintf and explicit NUL termination across URL/anchor parsing, discovery, and query construction.
Anchor & URL parsing
apps/cloud_proxy.c
url_to_udn/url_to_local_url now reject NULL and validate shapes/lengths; anchor_to_udn changed to bool, validates "ocf://" prefix, does bounded copying and signals failure.
D2D (di) management & resources
apps/cloud_proxy.c
Tightened if_di_exist, added find_di_index, updated remove_di to exact length+content matching with input bounds; find_resource signature now takes di_len; unregister_resources validates inputs and propagates new signature.
/d2dserverlist endpoints
apps/cloud_proxy.c
post_d2dserverlist/delete_d2dserverlist validate di query length, use bounded copying with explicit NUL termination, and only trigger discovery/requests when entries change; invalid di returns OC_STATUS_BAD_OPTION.
Proxied resource ops & separate responses
apps/cloud_proxy.c
get_resource/post_resource/delete_resource validate derived local_server, check oc_do_* results, and handle delayed-response allocation failures; separate-response callbacks validate user data, cap payloads via new get_separate_response_buffer_size() (guarded by OC_BLOCK_WISE), and free delayed buffers (notably on DELETE).
Discovery flow & UUID filter
apps/cloud_proxy.c
Discovery now requires successful anchor_to_udn; local udn_url built with length-checked memcpy (skips oversized paths); issue_requests uses snprintf for deviceuuid=... instead of strcat.
Unit test tweaks
api/unittest/discovery/discovery.h, api/unittest/enumstest.cpp
Added C++ <algorithm> include; improved compile-time enum comparison in enumstest.cpp to use the enum underlying type and safe casts for bounds checking.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: hardening parsing (URL, anchor, d2dserverlist validation) and async proxy error handling (null checks, response allocation, explicit error responses).
Description check ✅ Passed The description provides detailed coverage of all major changes in the PR, including overflow prevention, format validation, bounds checks, null checks, memory cleanup, DI handling improvements, and string concatenation fixes.
Docstring Coverage ✅ Passed Docstring coverage is 80.95% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jkralik/fix/cloud-proxy-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ocf-conformance-test-tool
Copy link
Copy Markdown

🎉 Thank you for your code contribution! To guarantee the change/addition is conformant to the OCF Specification, we would like to ask you to execute OCF Conformance Testing of your change ☝️ when your work is ready to be reviewed.


ℹ️ To verify your latest change (aefeb90), label this PR with OCF Conformance Testing.

⚠️ Label is removed with every code change.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/cloud_proxy.c (1)

1179-1194: Good error handling; consider removing unnecessary (int) cast.

The NULL check and payload size validation are excellent additions. However, line 1189 casts _payload_len to int unnecessarily—memcpy expects size_t. While the bounds check above prevents practical issues, the cast is a code smell.

Suggested cleanup
-  memcpy(delay_response->buffer, data->_payload, (int)data->_payload_len);
+  memcpy(delay_response->buffer, data->_payload, data->_payload_len);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cloud_proxy.c` around lines 1179 - 1194, The memcpy call currently casts
data->_payload_len to (int) which is unnecessary and a code smell; update the
memcpy invocation in the block handling delay_response to pass
data->_payload_len directly (or explicitly cast to size_t if the compiler
complains) as the third argument, e.g., memcpy(delay_response->buffer,
data->_payload, data->_payload_len), keeping the surrounding checks
(delay_response NULL, payload size vs get_separate_response_buffer_size(),
oc_send_separate_response, and free(delay_response)) unchanged and referencing
memcpy, data->_payload_len, delay_response, and oc_send_separate_response to
locate the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/cloud_proxy.c`:
- Around line 365-371: The extraction code in apps/cloud_proxy.c that computes
copy_len from anchor_len and prefix_len and writes into udn (using variables
copy_len, udn_size, memcpy, and udn[copy_len] = '\0') currently truncates when
copy_len >= udn_size and still returns true; change the logic so that if
copy_len >= udn_size (i.e., truncation would happen) the function returns false
instead of truncating and returning true, avoiding writing a partial UDN—ensure
no buffer overflow by only copying when copy_len < udn_size and return true on
success, false on truncation or other failure.

---

Nitpick comments:
In `@apps/cloud_proxy.c`:
- Around line 1179-1194: The memcpy call currently casts data->_payload_len to
(int) which is unnecessary and a code smell; update the memcpy invocation in the
block handling delay_response to pass data->_payload_len directly (or explicitly
cast to size_t if the compiler complains) as the third argument, e.g.,
memcpy(delay_response->buffer, data->_payload, data->_payload_len), keeping the
surrounding checks (delay_response NULL, payload size vs
get_separate_response_buffer_size(), oc_send_separate_response, and
free(delay_response)) unchanged and referencing memcpy, data->_payload_len,
delay_response, and oc_send_separate_response to locate the code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 68523ddf-1cc9-498c-bc90-5b998b9bb3cc

📥 Commits

Reviewing files that changed from the base of the PR and between 49441ba and aefeb90.

📒 Files selected for processing (1)
  • apps/cloud_proxy.c

Comment thread apps/cloud_proxy.c
Comment on lines +365 to +371
size_t copy_len = anchor_len - prefix_len;
if (copy_len >= udn_size) {
copy_len = udn_size - 1;
}
memcpy(udn, anchor + prefix_len, copy_len);
udn[copy_len] = '\0';
return true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Silent truncation returns true, which may mislead callers.

If the UDN portion of the anchor exceeds udn_size, the code truncates it but still returns true. This could lead to using an invalid/partial UDN that won't match any actual device, causing silent failures downstream.

Consider returning false when truncation occurs, so callers know the extraction failed:

Suggested fix
   size_t copy_len = anchor_len - prefix_len;
   if (copy_len >= udn_size) {
-    copy_len = udn_size - 1;
+    udn[0] = '\0';
+    return false;
   }
   memcpy(udn, anchor + prefix_len, copy_len);
   udn[copy_len] = '\0';
   return true;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
size_t copy_len = anchor_len - prefix_len;
if (copy_len >= udn_size) {
copy_len = udn_size - 1;
}
memcpy(udn, anchor + prefix_len, copy_len);
udn[copy_len] = '\0';
return true;
size_t copy_len = anchor_len - prefix_len;
if (copy_len >= udn_size) {
udn[0] = '\0';
return false;
}
memcpy(udn, anchor + prefix_len, copy_len);
udn[copy_len] = '\0';
return true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cloud_proxy.c` around lines 365 - 371, The extraction code in
apps/cloud_proxy.c that computes copy_len from anchor_len and prefix_len and
writes into udn (using variables copy_len, udn_size, memcpy, and udn[copy_len] =
'\0') currently truncates when copy_len >= udn_size and still returns true;
change the logic so that if copy_len >= udn_size (i.e., truncation would happen)
the function returns false instead of truncating and returning true, avoiding
writing a partial UDN—ensure no buffer overflow by only copying when copy_len <
udn_size and return true on success, false on truncation or other failure.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens cloud_proxy parsing and asynchronous proxying paths to reduce overflow risk and improve error handling/cleanup across discovery and GET/POST/DELETE proxy flows.

Changes:

  • Strengthened URL/anchor parsing (null/format checks, bounded copies) and safer DI handling in /d2dserverlist.
  • Added bounds checks and allocation/dispatch failure handling for separate responses in proxied GET/POST/DELETE flows.
  • Prevented path/query construction overflows in discovery and deviceuuid= query building.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/cloud_proxy.c
Comment on lines +365 to +371
size_t copy_len = anchor_len - prefix_len;
if (copy_len >= udn_size) {
copy_len = udn_size - 1;
}
memcpy(udn, anchor + prefix_len, copy_len);
udn[copy_len] = '\0';
return true;
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anchor_to_udn silently truncates the extracted UDN when the anchor value is longer than the destination buffer, but still returns true. Using a truncated device identifier can lead to incorrect device matching (and makes malformed/oversized anchors look valid). Prefer returning false (and leaving udn empty) when the UDN does not fully fit in udn_size.

Copilot uses AI. Check for mistakes.
Comment thread apps/cloud_proxy.c Outdated
Comment on lines 321 to 323
url_to_local_url(const char *url, size_t url_size, char *local_url,
size_t local_url_size)
{
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

url_to_local_url now expects url_size to be the URL string length (callers pass url_len), but the surrounding doc comment still describes url_size as the input URL buffer size. This mismatch makes the API easy to misuse. Please update the comment (and/or rename the parameter) to reflect that url_size is the string length.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ab3bd74. Renamed url_size to url_len in the function signature and updated the doc comment to clarify it's the string length (not including the null-terminator), matching how all callers pass url_len.

Comment thread apps/cloud_proxy.c
size_t max_payload = get_separate_response_buffer_size();
if (data->_payload_len > max_payload) {
OC_PRINTF("ERROR: payload too large for separate response buffer\n");
oc_send_separate_response(delay_response, OC_STATUS_INTERNAL_SERVER_ERROR);
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the local response payload exceeds the separate-response buffer, this sends OC_STATUS_INTERNAL_SERVER_ERROR. A more accurate status here is OC_STATUS_REQUEST_ENTITY_TOO_LARGE so the client can distinguish payload-size issues from server faults.

Suggested change
oc_send_separate_response(delay_response, OC_STATUS_INTERNAL_SERVER_ERROR);
oc_send_separate_response(delay_response,
OC_STATUS_REQUEST_ENTITY_TOO_LARGE);

Copilot uses AI. Check for mistakes.
Comment thread apps/cloud_proxy.c
size_t max_payload = get_separate_response_buffer_size();
if (data->_payload_len > max_payload) {
OC_PRINTF("ERROR: payload too large for separate response buffer\n");
oc_send_separate_response(delay_response, OC_STATUS_INTERNAL_SERVER_ERROR);
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the local response payload exceeds the separate-response buffer, this sends OC_STATUS_INTERNAL_SERVER_ERROR. A more accurate status here is OC_STATUS_REQUEST_ENTITY_TOO_LARGE so the client can distinguish payload-size issues from server faults.

Suggested change
oc_send_separate_response(delay_response, OC_STATUS_INTERNAL_SERVER_ERROR);
oc_send_separate_response(delay_response,
OC_STATUS_REQUEST_ENTITY_TOO_LARGE);

Copilot uses AI. Check for mistakes.
Comment thread apps/cloud_proxy.c
size_t max_payload = get_separate_response_buffer_size();
if (data->_payload_len > max_payload) {
OC_PRINTF("ERROR: payload too large for separate response buffer\n");
oc_send_separate_response(delay_response, OC_STATUS_INTERNAL_SERVER_ERROR);
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the local response payload exceeds the separate-response buffer, this sends OC_STATUS_INTERNAL_SERVER_ERROR. A more accurate status here is OC_STATUS_REQUEST_ENTITY_TOO_LARGE so the client can distinguish payload-size issues from server faults.

Suggested change
oc_send_separate_response(delay_response, OC_STATUS_INTERNAL_SERVER_ERROR);
oc_send_separate_response(delay_response,
OC_STATUS_REQUEST_ENTITY_TOO_LARGE);

Copilot uses AI. Check for mistakes.
Comment thread apps/cloud_proxy.c
Comment on lines 1225 to 1231
return;
}
char local_url[MAX_URI_LENGTH * 2] = { 0 };
if (!url_to_local_url(url, ARRAY_SIZE(url), local_url,
if (!url_to_local_url(url, url_len, local_url,
ARRAY_SIZE(local_url))) {
OC_PRINTF("ERROR: Could not extract local url from url");
return;
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On URL parsing failures (unable to extract UDN/local URL), the handler returns without sending any response. That can leave the cloud request hanging until timeout. Please send an explicit error response (eg. OC_STATUS_BAD_REQUEST / OC_STATUS_BAD_OPTION) before returning so malformed proxy URLs are rejected cleanly.

Copilot uses AI. Check for mistakes.
Comment thread apps/cloud_proxy.c
Comment on lines 1336 to 1342
return;
}
char local_url[MAX_URI_LENGTH * 2] = { 0 };
if (!url_to_local_url(url, ARRAY_SIZE(url), local_url,
if (!url_to_local_url(url, url_len, local_url,
ARRAY_SIZE(local_url))) {
OC_PRINTF("ERROR: Could not extract local url from url");
return;
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On URL parsing failures (unable to extract UDN/local URL), the handler returns without sending any response. That can leave the cloud request hanging until timeout. Please send an explicit error response (eg. OC_STATUS_BAD_REQUEST / OC_STATUS_BAD_OPTION) before returning so malformed proxy URLs are rejected cleanly.

Copilot uses AI. Check for mistakes.
Comment thread apps/cloud_proxy.c
Comment on lines 1466 to 1472
return;
}
char local_url[MAX_URI_LENGTH * 2] = { 0 };
if (!url_to_local_url(url, ARRAY_SIZE(url), local_url,
if (!url_to_local_url(url, url_len, local_url,
ARRAY_SIZE(local_url))) {
OC_PRINTF("ERROR: Could not extract local url from url");
return;
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On URL parsing failures (unable to extract UDN/local URL), the handler returns without sending any response. That can leave the cloud request hanging until timeout. Please send an explicit error response (eg. OC_STATUS_BAD_REQUEST / OC_STATUS_BAD_OPTION) before returning so malformed proxy URLs are rejected cleanly.

Copilot uses AI. Check for mistakes.
- update enumstest to compare enum bounds using the underlying enum type with unsigned conversion, avoiding signedness and range issues
- add missing algorithm include in discovery test header
- apply formatting-only cleanup in cloud_proxy for consistency (no functional changes)
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/cloud_proxy.c (1)

1212-1240: ⚠️ Potential issue | 🟠 Major

Send an explicit error before returning from these validation branches.

These handlers still return on malformed proxy URIs or oversized queries before a separate response is indicated. In those cases the cloud caller gets no 4xx/5xx at all, just a hung request.

Suggested fix pattern
   if (url_len >= ARRAY_SIZE(url)) {
     OC_PRINTF("ERROR: URI buffer too small");
+    oc_send_response(request, OC_STATUS_INTERNAL_SERVER_ERROR);
     return;
   }
   ...
   if (!url_to_udn(url, local_udn, ARRAY_SIZE(local_udn))) {
     OC_PRINTF("ERROR: Could not extract udn from url");
+    oc_send_response(request, OC_STATUS_BAD_REQUEST);
     return;
   }
   ...
   if (request->query_len >= ARRAY_SIZE(query_as_string)) {
     OC_PRINTF("ERROR: Query buffer too small");
+    oc_send_response(request, OC_STATUS_BAD_REQUEST);
     return;
   }

Apply the same pattern in get_resource, post_resource, and delete_resource.

Also applies to: 1322-1350, 1451-1479

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cloud_proxy.c` around lines 1212 - 1240, The validation branches in
get_resource (and similarly in post_resource and delete_resource) currently just
return on errors (e.g., when url_len >= ARRAY_SIZE(url), url_to_udn(...) fails,
url_to_local_url(...) fails, or request->query_len exceeds buffer) and leave the
caller hanging; before each early return send an explicit HTTP error response
using the same response path used elsewhere in these handlers (i.e., call the
module's normal error/response helper used by
get_resource/post_resource/delete_resource to send a 4xx/5xx with a descriptive
message) so the cloud caller receives a proper error code instead of a hung
request.
♻️ Duplicate comments (1)
apps/cloud_proxy.c (1)

365-371: ⚠️ Potential issue | 🟡 Minor

Reject oversized anchors instead of truncating them.

Line 367 still truncates an oversized anchor and Line 371 returns true. That feeds a partial UDN into discovery instead of rejecting malformed input.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cloud_proxy.c` around lines 365 - 371, Instead of truncating oversized
anchors, validate the computed copy length (copy_len = anchor_len - prefix_len)
against udn_size and reject by returning false before copying; specifically, in
the block that checks copy_len >= udn_size (using variables copy_len,
anchor_len, prefix_len, udn_size, udn), replace the truncation logic with an
early return false when copy_len > udn_size - 1 (or >= udn_size), and only
perform memcpy(udn, anchor + prefix_len, copy_len) and null-terminate udn when
the size fits.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/cloud_proxy.c`:
- Line 1733: Run clang-format over the reported hunk to fix spacing of the
trailing comment; specifically reformat the line containing the closing brace
and the comment "/* if loop */" so it matches project style (apply clang-format
to the block containing the brace and comment and stage the updated file
apps/cloud_proxy.c). Ensure only formatting changes are committed.
- Around line 717-723: The remove_di() loop currently only clears
g_d2dserverlist_d2dserverlist[i].di, leaking the corresponding
discovered_server[i] endpoint state; update remove_di() so when a DI match is
found you also free or reset the discovered_server entry (e.g., free
discovered_server[i].endpoint or call its cleanup/reset function, zero its
struct, and reset any allocation flags) before returning true, ensuring
discovered_server[i] does not retain stale allocated memory or state for reused
slots.
- Around line 742-745: The loop that searches app resources (using
oc_ri_get_app_resources and in unregister_resources) wrongly compares di to the
resource URI at byte 0; fix it to match registered proxy URIs of the form
"/<di>/...". Specifically, when iterating oc_resource_t *res and comparing
oc_string(res->uri) to di, compare starting at the character after the leading
'/' (e.g. compare oc_string(res->uri) + 1 to di for di_len bytes) and also
require that the character immediately after the matched di in the URI is '/'
(to ensure a "/<di>/" prefix), and apply the same change to the other loop
mentioned (lines 766-771).

---

Outside diff comments:
In `@apps/cloud_proxy.c`:
- Around line 1212-1240: The validation branches in get_resource (and similarly
in post_resource and delete_resource) currently just return on errors (e.g.,
when url_len >= ARRAY_SIZE(url), url_to_udn(...) fails, url_to_local_url(...)
fails, or request->query_len exceeds buffer) and leave the caller hanging;
before each early return send an explicit HTTP error response using the same
response path used elsewhere in these handlers (i.e., call the module's normal
error/response helper used by get_resource/post_resource/delete_resource to send
a 4xx/5xx with a descriptive message) so the cloud caller receives a proper
error code instead of a hung request.

---

Duplicate comments:
In `@apps/cloud_proxy.c`:
- Around line 365-371: Instead of truncating oversized anchors, validate the
computed copy length (copy_len = anchor_len - prefix_len) against udn_size and
reject by returning false before copying; specifically, in the block that checks
copy_len >= udn_size (using variables copy_len, anchor_len, prefix_len,
udn_size, udn), replace the truncation logic with an early return false when
copy_len > udn_size - 1 (or >= udn_size), and only perform memcpy(udn, anchor +
prefix_len, copy_len) and null-terminate udn when the size fits.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b154a773-dadb-4aaf-bb8b-a89570c635a4

📥 Commits

Reviewing files that changed from the base of the PR and between aefeb90 and 12c803c.

📒 Files selected for processing (3)
  • api/unittest/discovery/discovery.h
  • api/unittest/enumstest.cpp
  • apps/cloud_proxy.c
✅ Files skipped from review due to trivial changes (1)
  • api/unittest/discovery/discovery.h

Comment thread apps/cloud_proxy.c
Comment on lines 717 to 723
for (int i = 0; i < MAX_ARRAY; i++) {
OC_PRINTF(" %s %.*s ", g_d2dserverlist_d2dserverlist[i].di, len, di);
if (strncmp(g_d2dserverlist_d2dserverlist[i].di, di, len) == 0) {
size_t stored_len = strlen(g_d2dserverlist_d2dserverlist[i].di);
if (stored_len == (size_t)len &&
strncmp(g_d2dserverlist_d2dserverlist[i].di, di, (size_t)len) == 0) {
strcpy(g_d2dserverlist_d2dserverlist[i].di, "");
return true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Free the endpoint slot when removing a DI.

remove_di() only clears g_d2dserverlist_d2dserverlist[i].di. The endpoint copy in discovered_server[i] stays allocated, so add/remove cycles leak memory and reuse a slot with stale endpoint state.

Suggested fix
     if (stored_len == (size_t)len &&
         strncmp(g_d2dserverlist_d2dserverlist[i].di, di, (size_t)len) == 0) {
-      strcpy(g_d2dserverlist_d2dserverlist[i].di, "");
+      free(discovered_server[i]);
+      discovered_server[i] = NULL;
+      memset(&g_d2dserverlist_d2dserverlist[i], 0,
+             sizeof(g_d2dserverlist_d2dserverlist[i]));
       return true;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (int i = 0; i < MAX_ARRAY; i++) {
OC_PRINTF(" %s %.*s ", g_d2dserverlist_d2dserverlist[i].di, len, di);
if (strncmp(g_d2dserverlist_d2dserverlist[i].di, di, len) == 0) {
size_t stored_len = strlen(g_d2dserverlist_d2dserverlist[i].di);
if (stored_len == (size_t)len &&
strncmp(g_d2dserverlist_d2dserverlist[i].di, di, (size_t)len) == 0) {
strcpy(g_d2dserverlist_d2dserverlist[i].di, "");
return true;
for (int i = 0; i < MAX_ARRAY; i++) {
OC_PRINTF(" %s %.*s ", g_d2dserverlist_d2dserverlist[i].di, len, di);
size_t stored_len = strlen(g_d2dserverlist_d2dserverlist[i].di);
if (stored_len == (size_t)len &&
strncmp(g_d2dserverlist_d2dserverlist[i].di, di, (size_t)len) == 0) {
free(discovered_server[i]);
discovered_server[i] = NULL;
memset(&g_d2dserverlist_d2dserverlist[i], 0,
sizeof(g_d2dserverlist_d2dserverlist[i]));
return true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cloud_proxy.c` around lines 717 - 723, The remove_di() loop currently
only clears g_d2dserverlist_d2dserverlist[i].di, leaking the corresponding
discovered_server[i] endpoint state; update remove_di() so when a DI match is
found you also free or reset the discovered_server entry (e.g., free
discovered_server[i].endpoint or call its cleanup/reset function, zero its
struct, and reset any allocation flags) before returning true, ensuring
discovered_server[i] does not retain stale allocated memory or state for reused
slots.

Comment thread apps/cloud_proxy.c
Comment on lines 742 to 745
oc_resource_t *res = oc_ri_get_app_resources();
while (res != NULL) {
if (strncmp(di, oc_string(res->uri), strlen(di)) == 0)
if (strncmp(di, oc_string(res->uri), (size_t)di_len) == 0)
return res;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Match registered proxy URIs against /<di>/..., not di at byte 0.

Line 744 compares the query di directly against oc_string(res->uri), but proxied resources are registered as /<uuid>/.... unregister_resources() therefore misses every resource for that device, so DELETE /d2dserverlist?di=... leaves stale proxy resources behind.

Suggested fix
 STATIC oc_resource_t *
 find_resource(const char *di, int di_len)
 {
   if (di == NULL || di_len <= 0) {
     return NULL;
   }

   oc_resource_t *res = oc_ri_get_app_resources();
   while (res != NULL) {
-    if (strncmp(di, oc_string(res->uri), (size_t)di_len) == 0)
+    const char *uri = oc_string(res->uri);
+    if (uri != NULL && uri[0] == '/' &&
+        strncmp(uri + 1, di, (size_t)di_len) == 0 &&
+        (uri[di_len + 1] == '/' || uri[di_len + 1] == '\0')) {
       return res;
+    }
     res = res->next;
   }
-  return res;
+  return NULL;
 }

Also applies to: 766-771

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cloud_proxy.c` around lines 742 - 745, The loop that searches app
resources (using oc_ri_get_app_resources and in unregister_resources) wrongly
compares di to the resource URI at byte 0; fix it to match registered proxy URIs
of the form "/<di>/...". Specifically, when iterating oc_resource_t *res and
comparing oc_string(res->uri) to di, compare starting at the character after the
leading '/' (e.g. compare oc_string(res->uri) + 1 to di for di_len bytes) and
also require that the character immediately after the matched di in the URI is
'/' (to ensure a "/<di>/" prefix), and apply the same change to the other loop
mentioned (lines 766-771).

Comment thread apps/cloud_proxy.c

} /* adding current device, e.g. add the resource to the cloud RD */
} /* if loop */
} /* if loop */
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Run clang-format on this hunk.

The formatting job is already failing here; clang-format rewrites the trailing loop comment spacing on this line.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/cloud_proxy.c` at line 1733, Run clang-format over the reported hunk to
fix spacing of the trailing comment; specifically reformat the line containing
the closing brace and the comment "/* if loop */" so it matches project style
(apply clang-format to the block containing the brace and comment and stage the
updated file apps/cloud_proxy.c). Ensure only formatting changes are committed.

…length in doc comment

Agent-Logs-Url: https://github.com/iotivity/iotivity-lite/sessions/b976e73b-b795-4bd6-8741-a7d571f08bf3

Co-authored-by: jkralik <23374974+jkralik@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants