Heap buffer overflow in Curl_ipv4_resolve_r due to incorrect buffer alignment and size calculation on AmigaOS
What the report claims
Heap buffer overflow in Curl_ipv4_resolve_r due to incorrect buffer alignment and size calculation on AmigaOS
Compare with curl's recorded outcome
Labeled AI slop
curl's maintainer lists this report as AI slop
Shown for comparison after analysis. The pipeline did not see this label.
ProveIt's finding
The available evidence does not settle the report. A maintainer should investigate.
Why this finding?
- The core claim (C1) about incorrect alignment/size calculation depends on AmigaOS bsdsocket.library ABI and struct hostent definition, which are not in the provided curl source.
- The code uses sizeof(struct hostent) for the hostent buffer offset, which includes internal padding, but the data buffer pointer may need stricter alignment than the hostent structure provides.
- Without the platform-specific headers or documentation for gethostbyname_r, the claim cannot be confirmed or contradicted from the provided code alone.
- If the alignment issue exists, it would be a heap buffer overflow reachable via attacker-controlled hostnames (C5 supported), making it a plausible security issue on AmigaOS.
What still needs checking
- Definition of struct hostent on AmigaOS (from system headers)
- Signature and buffer alignment requirements of gethostbyname_r in bsdsocket.library
- AmigaOS SDK documentation for the reentrant resolver API
How this analysis ran 5 claims · 8 citations verified
Checked against curl master on 2025-12-17 (1b205078bd7f). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.
Review a draft reply to the reporter
Edit and verify before sending.
Thank you for the report. The code in lib/amigaos.c does show a fixed-size buffer (CURL_HOSTENT_SIZE=9000) split between struct hostent and a data buffer using sizeof(struct hostent). However, whether this calculation is incorrect depends on the alignment requirements of AmigaOS's bsdsocket.library gethostbyname_r and the definition of struct hostent, which are not in the curl source. Could you provide the relevant AmigaOS header definitions or bsdsocket.library documentation that specifies the required alignment for the data buffer pointer? This would allow us to verify if the offset (char *)buf + sizeof(struct hostent) meets the ABI requirements.
Inspect all claims and source code 5 claims · 3 code excerpts
Report claims
incorrect buffer alignment and size calculation
Read the reasoning
The code shows the buffer size calculation, but whether it is incorrect depends on the alignment requirements of the AmigaOS bsdsocket.library's gethostbyname_r and the definition of struct hostent, which are not in the provided source. sizeof(struct hostent) includes internal padding, but the data buffer pointer may need stricter alignment than the hostent structure's natural alignment. Without the platform ABI or header definitions, the claim cannot be verified from the provided code alone.
in lib/amigaos.c
Read the reasoning
The function Curl_ipv4_resolve_r is defined in lib/amigaos.c at line 123 in the provided source.
uses gethostbyname_r() with a fixed-size heap buffer
Read the reasoning
The code shows a fixed-size heap buffer (CURL_HOSTENT_SIZE = 9000) allocated via curlx_calloc and passed to gethostbyname_r.
may trigger heap memory corruption
Read the reasoning
Whether heap memory corruption can be triggered depends on whether C1 (incorrect alignment/size calculation) is true. Since C1 is not_verifiable from the provided code, the impact claim cannot be verified either.
DNS responses or resolution of attacker-controlled hostnames
Read the reasoning
The function resolves hostnames passed to it; an attacker who can influence DNS responses or control resolved hostnames could trigger this code path.
Read the original report
Source code
| 123 | struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port) |
| C2: Curl_ipv4_resolve_r defined in lib/amigaos.c | |
| C5: Curl_ipv4_resolve_r takes hostname parameter | |
| 124 | { |
| 125 | struct Curl_addrinfo *ai = NULL; |
| 126 | struct hostent *h; |
| 127 | struct SocketIFace *ISocket = __CurlISocket; |
| 128 | |
| 129 | if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) { |
| 130 | LONG h_errnop = 0; |
| 131 | struct hostent *buf; |
| 132 | |
| 133 | buf = curlx_calloc(1, CURL_HOSTENT_SIZE); |
| C1: Buffer allocated with curlx_calloc(1, CURL_HOSTENT_SIZE) | |
| C3: buf = curlx_calloc(1, CURL_HOSTENT_SIZE) allocates fixed-size heap buffer | |
| 134 | if(buf) { |
| 135 | h = gethostbyname_r((STRPTR)hostname, buf, |
| C1: gethostbyname_r called with data buffer at (char *)buf + sizeof(struct hostent) and size CURL_HOSTENT_SIZE - sizeof(struct hostent) | |
| C3: gethostbyname_r called with this buffer | |
| C5: hostname passed to gethostbyname_r | |
| 136 | (char *)buf + sizeof(struct hostent), |
| 137 | CURL_HOSTENT_SIZE - sizeof(struct hostent), |
| 138 | &h_errnop); |
| 139 | if(h) { |
| 140 | ai = Curl_he2ai(h, port); |
| 141 | } |
| 142 | curlx_free(buf); |
| 143 | } |
| 144 | } |
| 145 | else { |
| 146 | #ifdef CURLRES_THREADED |
| 147 | /* gethostbyname() is not thread-safe, so we need to reopen bsdsocket |
| 148 | * on the thread's context |
| 149 | */ |
| 150 | struct Library *base = OpenLibrary("bsdsocket.library", 4); |
| 151 | if(base) { |
| 152 | ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL); |
| 153 | if(ISocket) { |
| 154 | h = gethostbyname((STRPTR)hostname); |
| 155 | if(h) { |
| 156 | ai = Curl_he2ai(h, port); |
| 157 | } |
| 158 | DropInterface((struct Interface *)ISocket); |
| 159 | } |
| 160 | CloseLibrary(base); |
| 161 | } |
| 162 | #else |
| 163 | /* not using threaded resolver - safe to use this as-is */ |
| 164 | h = gethostbyname(hostname); |
| 165 | if(h) { |
| 166 | ai = Curl_he2ai(h, port); |
| 167 | } |
| 168 | #endif |
| 169 | } |
| 170 | |
| 171 | return ai; |
| 172 | } |
| 45 | #define CURL_HOSTENT_SIZE 9000 |
| C1: CURL_HOSTENT_SIZE defined as 9000 |
Show 51 lines (not cited by the judge)
| 127 | struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, |
| 128 | int port) |
| 129 | { |
| 130 | struct Curl_addrinfo *ai = NULL; |
| 131 | struct hostent *h; |
| 132 | struct SocketIFace *ISocket = __CurlISocket; |
| 133 | |
| 134 | if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) { |
| 135 | LONG h_errnop = 0; |
| 136 | struct hostent *buf; |
| 137 | |
| 138 | buf = calloc(1, CURL_HOSTENT_SIZE); |
| 139 | if(buf) { |
| 140 | h = gethostbyname_r((STRPTR)hostname, buf, |
| 141 | (char *)buf + sizeof(struct hostent), |
| 142 | CURL_HOSTENT_SIZE - sizeof(struct hostent), |
| 143 | &h_errnop); |
| 144 | if(h) { |
| 145 | ai = Curl_he2ai(h, port); |
| 146 | } |
| 147 | free(buf); |
| 148 | } |
| 149 | } |
| 150 | else { |
| 151 | #ifdef CURLRES_THREADED |
| 152 | /* gethostbyname() is not thread safe, so we need to reopen bsdsocket |
| 153 | * on the thread's context |
| 154 | */ |
| 155 | struct Library *base = OpenLibrary("bsdsocket.library", 4); |
| 156 | if(base) { |
| 157 | ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL); |
| 158 | if(ISocket) { |
| 159 | h = gethostbyname((STRPTR)hostname); |
| 160 | if(h) { |
| 161 | ai = Curl_he2ai(h, port); |
| 162 | } |
| 163 | DropInterface((struct Interface *)ISocket); |
| 164 | } |
| 165 | CloseLibrary(base); |
| 166 | } |
| 167 | #else |
| 168 | /* not using threaded resolver - safe to use this as-is */ |
| 169 | h = gethostbyname(hostname); |
| 170 | if(h) { |
| 171 | ai = Curl_he2ai(h, port); |
| 172 | } |
| 173 | #endif |
| 174 | } |
| 175 | |
| 176 | return ai; |
| 177 | } |