From owner-freebsd-bugs@FreeBSD.ORG Mon Feb 6 07:00:15 2006 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 89E7516A420 for ; Mon, 6 Feb 2006 07:00:15 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0A58A43D48 for ; Mon, 6 Feb 2006 07:00:15 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id k1670EWr066910 for ; Mon, 6 Feb 2006 07:00:14 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k1670EH1066908; Mon, 6 Feb 2006 07:00:14 GMT (envelope-from gnats) Resent-Date: Mon, 6 Feb 2006 07:00:14 GMT Resent-Message-Id: <200602060700.k1670EH1066908@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Andrey Simonenko Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3775716A422 for ; Mon, 6 Feb 2006 06:50:02 +0000 (GMT) (envelope-from simon@comsys.ntu-kpi.kiev.ua) Received: from comsys.ntu-kpi.kiev.ua (comsys.ntu-kpi.kiev.ua [195.245.194.142]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9EE0B43D5C for ; Mon, 6 Feb 2006 06:49:29 +0000 (GMT) (envelope-from simon@comsys.ntu-kpi.kiev.ua) Received: from pm513-1.comsys.ntu-kpi.kiev.ua (pm513-1.comsys.ntu-kpi.kiev.ua [10.18.52.101]) (authenticated bits=0) by comsys.ntu-kpi.kiev.ua (8.12.10/8.12.10) with ESMTP id k1671IVO041886 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Mon, 6 Feb 2006 09:01:19 +0200 (EET) Received: by pm513-1.comsys.ntu-kpi.kiev.ua (Postfix, from userid 1001) id C71535C021; Mon, 6 Feb 2006 08:49:09 +0200 (EET) Message-Id: <20060206064909.GA762@pm513-1.comsys.ntu-kpi.kiev.ua> Date: Mon, 6 Feb 2006 08:49:09 +0200 From: Andrey Simonenko To: FreeBSD-gnats-submit@FreeBSD.org Cc: Subject: bin/92880: [patch] almost rewritten inet_network(3) function X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 Feb 2006 07:00:15 -0000 >Number: 92880 >Category: bin >Synopsis: [patch] almost rewritten inet_network(3) function >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Feb 06 07:00:14 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Andrey Simonenko >Release: FreeBSD 6.0-STABLE i386 >Organization: >Environment: >Description: inet_network(3) function is not very safe, since it does not make all checks before converting string to network address. Rewritten version of inet_network() performs all checks (at least which I expect to see) and according to Assembler code it takes less space and should be a bit faster. Rewritten version also does not allow white space character at the end of parsed string. >How-To-Repeat: Here I insert a test program and output from this program (rewritten version of inet_network() is called inet_network_new() here): #include #include #include #include #include #include #include #include static in_addr_t inet_network_new(const char *cp) { u_char c; int got_data; u_int base, dots; in_addr_t res, val; res = 0; dots = 0; again: val = 0; got_data = 0; if (*cp == '0') { cp++; if (*cp == 'x' || *cp == 'X') { cp++; base = 16; } else { base = 8; got_data = 1; } } else base = 10; while ((c = *cp) != '\0') { if (isdigit(c)) { if (base == 8 && c > '7') return (INADDR_NONE); val = val * base + c - '0'; } else if (base == 16 && isxdigit(c)) val = (val << 4) + 10 - (islower(c) ? 'a' : 'A'); else break; if (val > 0xff) return (INADDR_NONE); cp++; got_data = 1; } if (!got_data) return (INADDR_NONE); if (dots != 0) res <<= 8; res |= val; if (c == '.') { if (++dots == 4) return (INADDR_NONE); cp++; goto again; } if (c != '\0') return (INADDR_NONE); return (res); } int main(void) { size_t len; in_addr_t addr; const char **addr_ptr; const char *addr_tbl[] = { "0x12", "127.1", "127.1.2.3", "0x123456", "0x12.0x34", "0x12.0x345", "1.2.3.4.5", "1..3.4", ".", "1.", ".1", "0x", "0", "01.02.07.077", "0x1.23.045.0", "", " ", "bar", "1.2bar", "1.", "йцукен", "255.255.255.255", "x", "0X12", "078", "1 bar", "127.0xfff", NULL }; printf("STRING\t\t\tINET_NETWORK\tINET_NETWORK_NEW\n"); for (addr_ptr = addr_tbl; *addr_ptr != NULL; ++addr_ptr) { printf("\"%s\"", *addr_ptr); len = strlen(*addr_ptr) + 2; if (len < 8) printf("\t\t\t"); else if (len < 16) printf("\t\t"); else printf("\t"); addr = inet_network(*addr_ptr); if (addr == INADDR_NONE) printf("INADDR_NONE\t"); else printf("0x%08x\t", addr); addr = inet_network_new(*addr_ptr); if (addr == INADDR_NONE) printf("INADDR_NONE\n"); else printf("0x%08x\n", addr); } return 0; } STRING INET_NETWORK INET_NETWORK_NEW "0x12" 0x00000012 0x00000012 "127.1" 0x00007f01 0x00007f01 "127.1.2.3" 0x7f010203 0x7f010203 "0x123456" 0x00000056 INADDR_NONE "0x12.0x34" 0x00001234 0x00001234 "0x12.0x345" 0x00001245 INADDR_NONE "1.2.3.4.5" INADDR_NONE INADDR_NONE "1..3.4" 0x01000304 INADDR_NONE "." 0x00000000 INADDR_NONE "1." 0x00000100 INADDR_NONE ".1" 0x00000001 INADDR_NONE "0x" 0x00000000 INADDR_NONE "0" 0x00000000 0x00000000 "01.02.07.077" 0x0102073f 0x0102073f "0x1.23.045.0" 0x01172500 0x01172500 "" 0x00000000 INADDR_NONE " " 0x00000000 INADDR_NONE "bar" INADDR_NONE INADDR_NONE "1.2bar" INADDR_NONE INADDR_NONE "1." 0x00000100 INADDR_NONE "йцукен" INADDR_NONE INADDR_NONE "255.255.255.255" INADDR_NONE INADDR_NONE "x" 0x00000000 INADDR_NONE "0X12" 0x00000012 0x00000012 "078" 0x00000040 INADDR_NONE "1 bar" 0x00000001 INADDR_NONE "127.0xfff" 0x00007fff INADDR_NONE >Fix: --- inet_network.c.orig Fri Mar 22 23:52:29 2002 +++ inet_network.c Sun Feb 5 22:21:14 2006 @@ -48,48 +48,58 @@ * network numbers. */ in_addr_t -inet_network(cp) - const char *cp; +inet_network(const char *cp) { - in_addr_t val, base, n; - char c; - in_addr_t parts[4], *pp = parts; - int i; + u_char c; + int got_data; + u_int base, dots; + in_addr_t res, val; + + res = 0; + dots = 0; again: - val = 0; base = 10; - if (*cp == '0') - base = 8, cp++; - if (*cp == 'x' || *cp == 'X') - base = 16, cp++; - while ((c = *cp) != 0) { - if (isdigit((unsigned char)c)) { - val = (val * base) + (c - '0'); - cp++; - continue; - } - if (base == 16 && isxdigit((unsigned char)c)) { - val = (val << 4) + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); + val = 0; + got_data = 0; + if (*cp == '0') { + cp++; + if (*cp == 'x' || *cp == 'X') { cp++; - continue; + base = 16; + } else { + base = 8; + got_data = 1; } - break; + } else + base = 10; + while ((c = *cp) != '\0') { + if (isdigit(c)) { + if (base == 8 && c > '7') + return (INADDR_NONE); + val = val * base + c - '0'; + } else if (base == 16 && isxdigit(c)) + val = (val << 4) + 10 - (islower(c) ? 'a' : 'A'); + else + break; + if (val > 0xff) + return (INADDR_NONE); + cp++; + got_data = 1; } - if (*cp == '.') { - if (pp >= parts + 3) + if (!got_data) + return (INADDR_NONE); + if (dots != 0) + res <<= 8; + res |= val; + if (c == '.') { + if (++dots == 4) return (INADDR_NONE); - *pp++ = val, cp++; + cp++; goto again; } - if (*cp && !isspace((unsigned char)*cp)) + if (c != '\0') return (INADDR_NONE); - *pp++ = val; - n = pp - parts; - for (val = 0, i = 0; i < n; i++) { - val <<= 8; - val |= parts[i] & 0xff; - } - return (val); + return (res); } /* >Release-Note: >Audit-Trail: >Unformatted: