Skip to content

Commit 7ae8fb1

Browse files
authored
fix pointer overflow check
Signed-off-by: Hasan ÇALIŞIR <hasan.calisir@psauxit.com>
1 parent d4d431d commit 7ae8fb1

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

safexec/libnpp_norm.c

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ static void pctnorm_load_config(void) {
199199
}
200200
static inline void ensure_config(void) { (void)pthread_once(&config_once, pctnorm_load_config); }
201201

202-
203202
/* Lazy re-resolve TLS symbols in case libssl/gnutls were dlopen()'d later. */
204203
#if PCT_WANT_TLS
205204
static inline void resolve_tls_if_needed(void) {
@@ -242,47 +241,81 @@ static void collect_triplet_cases_from_segment(const char *s) {
242241
}
243242
}
244243

244+
/* Bounded substring search: returns pointer to first occurrence of needle
245+
in haystack (bounded by hlen), or NULL if not found. */
246+
static inline const char *bounded_strstr_n(const char *hay, size_t hlen,
247+
const char *needle, size_t nlen)
248+
{
249+
if (!hay || !needle || nlen == 0) return hay;
250+
if (hlen < nlen) return NULL;
251+
252+
#if defined(__GLIBC__) || defined(__linux__) || defined(__APPLE__) || \
253+
defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
254+
return (const char *)memmem(hay, hlen, needle, nlen);
255+
#else
256+
const char *end = hay + (hlen - nlen) + 1;
257+
for (const char *p = hay; p < end; ++p) {
258+
if (p[0] == needle[0] && memcmp(p, needle, nlen) == 0)
259+
return p;
260+
}
261+
return NULL;
262+
#endif
263+
}
264+
245265
/* crude but safe parse of first http(s) URL in /proc/self/cmdline and capture path+query */
246266
static void init_argv_triplet_map(void) {
247267
int fd = open("/proc/self/cmdline", O_RDONLY);
248268
if (fd < 0) return;
269+
249270
char buf[8192];
250271
ssize_t n = read(fd, buf, sizeof buf - 1);
251272
close(fd);
252273
if (n <= 0) return;
274+
275+
/* Add a sentinel NUL so plain C-string ops on copies are safe.
276+
The valid range is [buf, buf+n). endbuf does NOT include extra NUL. */
253277
buf[n] = '\0';
278+
char *p = buf;
279+
char *endbuf = buf + n;
254280

255281
/* /proc/self/cmdline is NUL-separated argv */
256-
char *p = buf;
257-
while (p < buf + n) {
258-
size_t len = strlen(p);
282+
while (p < endbuf) {
283+
size_t remain = (size_t)(endbuf - p);
284+
285+
/* Find next NUL within bounds */
286+
const char *nul = memchr(p, '\0', remain);
287+
if (!nul) break;
288+
size_t len = (size_t)(nul - p);
259289
if (len == 0) break;
260290

261291
if (!strncasecmp(p, "http://", 7) || !strncasecmp(p, "https://", 8)) {
262292
const char *u = p;
263-
const char *path = strstr(u, "://");
293+
const char *path = bounded_strstr_n(u, len, "://", 3);
264294
if (path) {
265-
path += 3; /* skip "://" */
295+
path += 3;
296+
266297
/* skip authority host[:port] */
267298
while (*path && *path != '/' && *path != '?' && *path != '#') path++;
299+
268300
/* capture path + query (fragment not transmitted) */
269301
if (*path == '/' || *path == '?') {
270-
/* terminate at '#' or NUL */
271302
const char *end = path;
272303
while (*end && *end != '#') end++;
273-
char *tmp = (char*)malloc((size_t)(end - path + 1));
304+
305+
size_t seglen = (size_t)(end - path);
306+
char *tmp = (char*)malloc(seglen + 1);
274307
if (tmp) {
275-
memcpy(tmp, path, (size_t)(end - path));
276-
tmp[end - path] = '\0';
308+
memcpy(tmp, path, seglen);
309+
tmp[seglen] = '\0';
277310
collect_triplet_cases_from_segment(tmp);
278311
free(tmp);
279312
}
280313
}
281314
}
282-
break; /* only first URL */
315+
break;
283316
}
284317

285-
p += len + 1;
318+
p = (char *)nul + 1;
286319
}
287320
}
288321

0 commit comments

Comments
 (0)