Skip to content

Conversation

puppywang
Copy link

Hello Orbbec SDK Team,

This pull request fixes a critical heap-use-after-free race condition in the GigE Vision (GVCP) client implementation.

The Issue

When running an application that uses the SDK with AddressSanitizer (ASan) enabled, a crash can be reliably triggered within the asynchronous logging mechanism. The root cause is located in GVCPClient::openClientSocket.

The code passes a pointer returned by inet_ntoa() directly to the LOG_INTVL macro. The inet_ntoa function is known to return a pointer to a temporary, thread-local static buffer.

Because LOG_INTVL is an asynchronous logger that spawns a new thread to handle the actual printing, it only captures the temporary pointer, not the string data itself. By the time the background logging thread attempts to read from this pointer, the original thread may have exited or called inet_ntoa again, causing the static buffer to be freed or overwritten. This leads to a heap-use-after-free error.

The Fix

The solution is to ensure the string data is copied before being passed to the asynchronous logger. This is achieved by wrapping the inet_ntoa() call in std::string(). This creates a std::string object with its own copy of the data, which can be safely captured and used by the background thread.

The change is very small and localized to GVCPClient.cpp:

// In GVCPClient::openClientSocket
// Before:
LOG_INTVL(..., "bind {}:{}", inet_ntoa(addr.sin_addr), ...);

// After:
LOG_INTVL(..., "bind {}:{}", std::string(inet_ntoa(addr.sin_addr)), ...);

How to Verify

Compile the SDK from source in Debug mode with AddressSanitizer enabled on Windows (using MSVC's /fsanitize=address flag).

Run an application that initializes a network device using ob::Context::createNetDevice().

The application will likely crash with a heap-use-after-free error reported by ASan, with the call stack pointing to spdlog and the memory being freed during thread exit.

Apply this patch and recompile.

The crash will no longer occur.

This fix improves the stability and thread safety of the SDK's logging system, especially in complex applications where threads are created and destroyed frequently.

Thank you for your time and for maintaining this project!

The function inet_ntoa returns a pointer to a temporary, thread-local
static buffer. In GVCPClient::openClientSocket, this temporary pointer
was being passed directly to the asynchronous LOG_INTVL macro.

This created a race condition where the background logging thread could
attempt to access the pointer after the static buffer's content was
no longer valid (e.g., after the calling thread exited). This resulted
in a heap-use-after-free error, which was reliably detected by
AddressSanitizer.

The fix is to wrap the call to inet_ntoa in std::string(), ensuring
that a copy of the string data is made immediately. This safe copy is
then passed to the asynchronous logger, resolving the lifetime issue.
@zhonghong322
Copy link
Contributor

Thank you for your feedback on this issue. We have fixed it, and the update will be released in the next version.

- Prevent overwriting caller-provided localAddress_ in checkLocalIP()
- Prioritize subnet-matching IP for destination address
- Fallback to first private IPv4 if no match, or clear for OS decision
- Ensure correct bind() in socketConnect() to avoid wrong source IP in packets
- Addresses issue where packets were sent from wrong IP (e.g., 192.168.1.107 instead of 192.168.2.165) on adapters with multiple IPs
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.

2 participants