Thu Nov 22 18:42:06 2018 UTC ()
add an assert() check on array bounds.


(mrg)
diff -r1.42 -r1.43 src/libexec/httpd/cgi-bozo.c

cvs diff -r1.42 -r1.43 src/libexec/httpd/cgi-bozo.c (expand / switch to unified diff)

--- src/libexec/httpd/cgi-bozo.c 2018/11/22 08:54:08 1.42
+++ src/libexec/httpd/cgi-bozo.c 2018/11/22 18:42:06 1.43
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: cgi-bozo.c,v 1.42 2018/11/22 08:54:08 mrg Exp $ */ 1/* $NetBSD: cgi-bozo.c,v 1.43 2018/11/22 18:42:06 mrg Exp $ */
2 2
3/* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */ 3/* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */
4 4
5/* 5/*
6 * Copyright (c) 1997-2018 Matthew R. Green 6 * Copyright (c) 1997-2018 Matthew R. Green
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -35,26 +35,27 @@ @@ -35,26 +35,27 @@
35#ifndef NO_CGIBIN_SUPPORT 35#ifndef NO_CGIBIN_SUPPORT
36 36
37#include <sys/param.h> 37#include <sys/param.h>
38#include <sys/socket.h> 38#include <sys/socket.h>
39 39
40#include <ctype.h> 40#include <ctype.h>
41#include <errno.h> 41#include <errno.h>
42#include <paths.h> 42#include <paths.h>
43#include <signal.h> 43#include <signal.h>
44#include <stdlib.h> 44#include <stdlib.h>
45#include <string.h> 45#include <string.h>
46#include <syslog.h> 46#include <syslog.h>
47#include <unistd.h> 47#include <unistd.h>
 48#include <assert.h>
48 49
49#include <netinet/in.h> 50#include <netinet/in.h>
50 51
51#include "bozohttpd.h" 52#include "bozohttpd.h"
52 53
53#define CGIBIN_PREFIX "cgi-bin/" 54#define CGIBIN_PREFIX "cgi-bin/"
54#define CGIBIN_PREFIX_LEN (sizeof(CGIBIN_PREFIX)-1) 55#define CGIBIN_PREFIX_LEN (sizeof(CGIBIN_PREFIX)-1)
55 56
56#ifndef USE_ARG 57#ifndef USE_ARG
57#define USE_ARG(x) /*LINTED*/(void)&(x) 58#define USE_ARG(x) /*LINTED*/(void)&(x)
58#endif 59#endif
59 60
60/* 61/*
@@ -370,26 +371,27 @@ bozo_setenv(bozohttpd_t *httpd, const ch @@ -370,26 +371,27 @@ bozo_setenv(bozohttpd_t *httpd, const ch
370 * process the cgi, otherwise just return. Returns 0 if it did not handle 371 * process the cgi, otherwise just return. Returns 0 if it did not handle
371 * the request. 372 * the request.
372 */ 373 */
373int 374int
374bozo_process_cgi(bozo_httpreq_t *request) 375bozo_process_cgi(bozo_httpreq_t *request)
375{ 376{
376 bozohttpd_t *httpd = request->hr_httpd; 377 bozohttpd_t *httpd = request->hr_httpd;
377 char buf[BOZO_WRSZ]; 378 char buf[BOZO_WRSZ];
378 char date[40]; 379 char date[40];
379 bozoheaders_t *headp; 380 bozoheaders_t *headp;
380 const char *type, *clen, *info, *cgihandler; 381 const char *type, *clen, *info, *cgihandler;
381 char *query, *s, *t, *path, *env, *command, *file, *url; 382 char *query, *s, *t, *path, *env, *command, *file, *url;
382 char **envp, **curenvp, **argv, **search_string_argv = NULL; 383 char **envp, **curenvp, **argv, **search_string_argv = NULL;
 384 char **lastenvp;
383 char *uri; 385 char *uri;
384 size_t i, len, search_string_argc = 0; 386 size_t i, len, search_string_argc = 0;
385 ssize_t rbytes; 387 ssize_t rbytes;
386 pid_t pid; 388 pid_t pid;
387 int envpsize, ix, nph; 389 int envpsize, ix, nph;
388 int sv[2]; 390 int sv[2];
389 391
390 if (!httpd->cgibin && !httpd->process_cgi) 392 if (!httpd->cgibin && !httpd->process_cgi)
391 return 0; 393 return 0;
392 394
393#ifndef NO_USER_SUPPORT 395#ifndef NO_USER_SUPPORT
394 if (request->hr_user && !httpd->enable_cgi_users) 396 if (request->hr_user && !httpd->enable_cgi_users)
395 return 0; 397 return 0;
@@ -496,26 +498,27 @@ bozo_process_cgi(bozo_httpreq_t *request @@ -496,26 +498,27 @@ bozo_process_cgi(bozo_httpreq_t *request
496 bozo_auth_cgi_count(request) + 498 bozo_auth_cgi_count(request) +
497 (request->hr_serverport && *request->hr_serverport ? 1 : 0); 499 (request->hr_serverport && *request->hr_serverport ? 1 : 0);
498 500
499 debug((httpd, DEBUG_FAT, 501 debug((httpd, DEBUG_FAT,
500 "%s: path `%s', cmd `%s', info `%s', " 502 "%s: path `%s', cmd `%s', info `%s', "
501 "query `%s', nph `%d', envpsize `%d'", __func__, 503 "query `%s', nph `%d', envpsize `%d'", __func__,
502 path, command, strornull(info), 504 path, command, strornull(info),
503 strornull(query), nph, envpsize)); 505 strornull(query), nph, envpsize));
504 506
505 envp = bozomalloc(httpd, sizeof(*envp) * envpsize); 507 envp = bozomalloc(httpd, sizeof(*envp) * envpsize);
506 for (ix = 0; ix < envpsize; ix++) 508 for (ix = 0; ix < envpsize; ix++)
507 envp[ix] = NULL; 509 envp[ix] = NULL;
508 curenvp = envp; 510 curenvp = envp;
 511 lastenvp = envp + envpsize;
509 512
510 SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next) { 513 SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next) {
511 const char *s2; 514 const char *s2;
512 env = bozomalloc(httpd, 6 + strlen(headp->h_header) + 1 + 515 env = bozomalloc(httpd, 6 + strlen(headp->h_header) + 1 +
513 strlen(headp->h_value)); 516 strlen(headp->h_value));
514 517
515 t = env; 518 t = env;
516 strcpy(t, "HTTP_"); 519 strcpy(t, "HTTP_");
517 t += strlen(t); 520 t += strlen(t);
518 for (s2 = headp->h_header; *s2; t++, s2++) 521 for (s2 = headp->h_header; *s2; t++, s2++)
519 if (islower((unsigned)*s2)) 522 if (islower((unsigned)*s2))
520 *t = toupper((unsigned)*s2); 523 *t = toupper((unsigned)*s2);
521 else if (*s2 == '-') 524 else if (*s2 == '-')
@@ -577,26 +580,27 @@ bozo_process_cgi(bozo_httpreq_t *request @@ -577,26 +580,27 @@ bozo_process_cgi(bozo_httpreq_t *request
577 debug((httpd, DEBUG_FAT, "%s: going exec %s with args:", __func__, 580 debug((httpd, DEBUG_FAT, "%s: going exec %s with args:", __func__,
578 path)); 581 path));
579 582
580 for (i = 0; argv[i] != NULL; i++) { 583 for (i = 0; argv[i] != NULL; i++) {
581 debug((httpd, DEBUG_FAT, "%s: argv[%zu] = `%s'", __func__, 584 debug((httpd, DEBUG_FAT, "%s: argv[%zu] = `%s'", __func__,
582 i, argv[i])); 585 i, argv[i]));
583 } 586 }
584 587
585 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1) 588 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1)
586 bozoerr(httpd, 1, "child socketpair failed: %s", 589 bozoerr(httpd, 1, "child socketpair failed: %s",
587 strerror(errno)); 590 strerror(errno));
588 591
589 *curenvp = 0; 592 *curenvp = 0;
 593 assert(lastenvp > curenvp);
590 594
591 /* 595 /*
592 * We create 2 procs: one to become the CGI, one read from 596 * We create 2 procs: one to become the CGI, one read from
593 * the CGI and output to the network, and this parent will 597 * the CGI and output to the network, and this parent will
594 * continue reading from the network and writing to the 598 * continue reading from the network and writing to the
595 * CGI procsss. 599 * CGI procsss.
596 */ 600 */
597 switch (fork()) { 601 switch (fork()) {
598 case -1: /* eep, failure */ 602 case -1: /* eep, failure */
599 bozoerr(httpd, 1, "child fork failed: %s", strerror(errno)); 603 bozoerr(httpd, 1, "child fork failed: %s", strerror(errno));
600 /*NOTREACHED*/ 604 /*NOTREACHED*/
601 case 0: 605 case 0:
602 close(sv[0]); 606 close(sv[0]);