From patchwork Mon Nov 16 15:59:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael McConville X-Patchwork-Id: 545077 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id E7EEB141469 for ; Tue, 17 Nov 2015 02:59:41 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=wEaJvyW3; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:content-type; q=dns; s=default; b=YT 6GPZFMJawtl3xqBftRLWHTMnsIPoP2ihwys/Lvc7cV0X75sg/HPv7Y1+Tj/+pwhe yYEm0UJME4s2petiSYN2wMXwdRhBhl71LTrP00+q9U10LzjJaG+QC709lHE6VDhF fonQisFR6F6oDELJ1Cevfo//TAOZy3aceVHvOLfwA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:content-type; s=default; bh=Ia+rsQF7 P6GegiMdmSYe2pZqW7c=; b=wEaJvyW3jMoKLF2Fabsk2DqiWDioOWgUc+S/KI02 x74kr9r/mswGBhnbZ7ZugJiyWOn8W2aMUCRpjQCOpPViLrSjW/L9zwxqTPxPrAtm avn2/aNS7XpD9FlTCVFfLNIN8DU8JYrFl2oItf+LdR4VRKJqwojJPiGiBYXX8d4/ 5U4= Received: (qmail 49491 invoked by alias); 16 Nov 2015 15:59:33 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 49481 invoked by uid 89); 16 Nov 2015 15:59:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx-out01.mykolab.com Received: from mx01.mykolab.com (HELO mx-out01.mykolab.com) (95.128.36.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Mon, 16 Nov 2015 15:59:29 +0000 X-Spam-Score: -3.672 Received: from mx03.mykolab.com (mx03.mykolab.com [10.20.7.101]) by mx-out01.mykolab.com (Postfix) with ESMTPS id 8E053601DF for ; Mon, 16 Nov 2015 16:59:23 +0100 (CET) Date: Mon, 16 Nov 2015 10:59:20 -0500 From: Michael McConville To: gcc-patches@gcc.gnu.org Subject: [PATCH] ctype functions and signedness Message-ID: <20151116155919.GA13057@thinkpad.swarthmore.edu> Content-Disposition: inline Hi, everyone. While it often (usually?) isn't an issue, passing a signed char to ctype functions is undefined. Here's the CERT entry: https://www.securecoding.cert.org/confluence/x/fAs This means that we need to cast chars to unsigned char before passing them to one of these functions. The below patch, generated by a Coccinelle script, fixes instances of this. It may need some minor tweaks to add line breaks and conform with local style conventions. Thanks, Michael --- boehm-gc/cord/de_win.c +++ /tmp/cocci-output-25514-78f80b-de_win.c @@ -86,7 +86,7 @@ int APIENTRY WinMain (HINSTANCE hInstanc } else { char *p = command_line; - while (*p != 0 && !isspace(*p)) p++; + while (*p != 0 && !isspace((unsigned char)*p)) p++; arg_file_name = CORD_to_char_star( CORD_substr(command_line, 0, p - command_line)); } @@ -129,7 +129,7 @@ char * plain_chars(char * text, size_t l register size_t i; for (i = 0; i < len; i++) { - if (iscntrl(text[i])) { + if (iscntrl((unsigned char)text[i])) { result[i] = ' '; } else { result[i] = text[i]; @@ -147,7 +147,7 @@ char * control_chars(char * text, size_t register size_t i; for (i = 0; i < len; i++) { - if (iscntrl(text[i])) { + if (iscntrl((unsigned char)text[i])) { result[i] = text[i] + 0x40; } else { result[i] = ' '; --- boehm-gc/os_dep.c +++ /tmp/cocci-output-25514-d4c0bc-os_dep.c @@ -271,31 +271,31 @@ char *GC_parse_map_entry(char *buf_ptr, } p = buf_ptr; - while (isspace(*p)) ++p; + while (isspace((unsigned char)*p)) ++p; start_start = p; - GC_ASSERT(isxdigit(*start_start)); + GC_ASSERT(isxdigit((unsigned char)*start_start)); *start = strtoul(start_start, &endp, 16); p = endp; GC_ASSERT(*p=='-'); ++p; end_start = p; - GC_ASSERT(isxdigit(*end_start)); + GC_ASSERT(isxdigit((unsigned char)*end_start)); *end = strtoul(end_start, &endp, 16); p = endp; - GC_ASSERT(isspace(*p)); + GC_ASSERT(isspace((unsigned char)*p)); - while (isspace(*p)) ++p; + while (isspace((unsigned char)*p)) ++p; prot_start = p; GC_ASSERT(*prot_start == 'r' || *prot_start == '-'); memcpy(prot_buf, prot_start, 4); prot_buf[4] = '\0'; if (prot_buf[1] == 'w') {/* we can skip the rest if it's not writable. */ /* Skip past protection field to offset field */ - while (!isspace(*p)) ++p; while (isspace(*p)) ++p; - GC_ASSERT(isxdigit(*p)); + while (!isspace((unsigned char)*p)) ++p; while (isspace((unsigned char)*p)) ++p; + GC_ASSERT(isxdigit((unsigned char)*p)); /* Skip past offset field, which we ignore */ - while (!isspace(*p)) ++p; while (isspace(*p)) ++p; + while (!isspace((unsigned char)*p)) ++p; while (isspace((unsigned char)*p)) ++p; maj_dev_start = p; - GC_ASSERT(isxdigit(*maj_dev_start)); + GC_ASSERT(isxdigit((unsigned char)*maj_dev_start)); *maj_dev = strtoul(maj_dev_start, NULL, 16); } @@ -969,11 +969,11 @@ ptr_t GC_get_stack_base() /* Skip the required number of fields. This number is hopefully */ /* constant across all Linux implementations. */ for (i = 0; i < STAT_SKIP; ++i) { - while (isspace(c)) c = stat_buf[buf_offset++]; - while (!isspace(c)) c = stat_buf[buf_offset++]; + while (isspace((unsigned char)c)) c = stat_buf[buf_offset++]; + while (!isspace((unsigned char)c)) c = stat_buf[buf_offset++]; } - while (isspace(c)) c = stat_buf[buf_offset++]; - while (isdigit(c)) { + while (isspace((unsigned char)c)) c = stat_buf[buf_offset++]; + while (isdigit((unsigned char)c)) { result *= 10; result += c - '0'; c = stat_buf[buf_offset++]; --- gcc/testsuite/gcc.dg/charset/builtin1.c +++ /tmp/cocci-output-20442-6d79bd-builtin1.c @@ -14,9 +14,9 @@ static int strA(void) { return 'A'; } int main(void) { - if (!isdigit('1')) + if (!isdigit((unsigned char)'1')) abort(); - if (isdigit('A')) + if (isdigit((unsigned char)'A')) abort(); if (!isdigit(str1())) abort(); --- gcc/testsuite/gcc.dg/torture/pr67821.c +++ /tmp/cocci-output-18483-79f7b5-pr67821.c @@ -7,9 +7,9 @@ foo (const char *s) { int success = 1; const char *p = s + 2; - if (!isdigit (*p)) + if (!isdigit ((unsigned char)*p)) success = 0; - while (isdigit (*p)) + while (isdigit ((unsigned char)*p)) ++p; return success; } --- gcc/ada/adaint.c +++ /tmp/cocci-output-21151-00798e-adaint.c @@ -1628,7 +1628,7 @@ __gnat_is_absolute_path (char *name, int { if (name[index] == ':' && ((name[index + 1] == '/') || - (isalpha (name[index + 1]) && index + 2 <= length && + (isalpha ((unsigned char)name[index + 1]) && index + 2 <= length && name[index + 2] == '/'))) return 1; --- gcc/config/darwin.c +++ /tmp/cocci-output-11137-daf870-darwin.c @@ -3471,7 +3471,7 @@ darwin_build_constant_cfstring (tree str int l = 0; for (l = 0; l < length; l++) - if (!s[l] || !isascii (s[l])) + if (!s[l] || !isascii ((unsigned char)s[l])) { warning (darwin_warn_nonportable_cfstrings, "%s in CFString literal", s[l] ? "non-ASCII character" : "embedded NUL"); --- libcpp/makeucnid.c +++ /tmp/cocci-output-1465-01eaaf-makeucnid.c @@ -81,7 +81,7 @@ read_ucnid (const char *fname) fl = C11; else if (strcmp (line, "[C11NOSTART]\n") == 0) fl = C11|N11; - else if (isxdigit (line[0])) + else if (isxdigit ((unsigned char)line[0])) { char *l = line; while (*l) @@ -89,7 +89,7 @@ read_ucnid (const char *fname) unsigned long start, end; char *endptr; start = strtoul (l, &endptr, 16); - if (endptr == l || (*endptr != '-' && ! isspace (*endptr))) + if (endptr == l || (*endptr != '-' && ! isspace ((unsigned char)*endptr))) fail ("parsing ucnid.tab [1]"); l = endptr; if (*l != '-') @@ -100,10 +100,10 @@ read_ucnid (const char *fname) if (end < start) fail ("parsing ucnid.tab, end before start"); l = endptr; - if (! isspace (*l)) + if (! isspace ((unsigned char)*l)) fail ("parsing ucnid.tab, junk after range"); } - while (isspace (*l)) + while (isspace ((unsigned char)*l)) l++; if (end > MAX_CODE_POINT) fail ("parsing ucnid.tab, end too large"); @@ -156,7 +156,7 @@ read_table (char *fname) } while (*l != ';'); /* Canonical combining class; in NFC/NFKC, they must be increasing (or zero). */ - if (! isdigit (*++l)) + if (! isdigit ((unsigned char)*++l)) fail ("parsing UnicodeData.txt, combining class not number"); combining_value[codepoint] = strtoul (l, &l, 10); if (*l++ != ';') @@ -175,11 +175,11 @@ read_table (char *fname) { if (*l == ';') break; - if (!isxdigit (*l)) + if (!isxdigit ((unsigned char)*l)) fail ("parsing UnicodeData.txt, decomposition format"); this_decomp[i] = strtoul (l, &l, 16); decomp_useful &= flags[this_decomp[i]]; - while (isspace (*l)) + while (isspace ((unsigned char)*l)) l++; } if (i > 2) /* Decomposition too long. */ --- libgfortran/runtime/environ.c +++ /tmp/cocci-output-8814-ef5a91-environ.c @@ -80,7 +80,7 @@ init_integer (variable * v) return; for (q = p; *q; q++) - if (!isdigit (*q) && (p != q || *q != '-')) + if (!isdigit ((unsigned char)*q) && (p != q || *q != '-')) return; *v->var = atoi (p); @@ -99,7 +99,7 @@ init_unsigned_integer (variable * v) return; for (q = p; *q; q++) - if (!isdigit (*q)) + if (!isdigit ((unsigned char)*q)) return; *v->var = atoi (p); @@ -348,7 +348,7 @@ static int match_integer (void) { unit_num = 0; - while (isdigit (*p)) + while (isdigit ((unsigned char)*p)) unit_num = unit_num * 10 + (*p++ - '0'); return INTEGER; } --- libgfortran/io/list_read.c +++ /tmp/cocci-output-7054-3fc663-list_read.c @@ -2656,7 +2656,7 @@ nml_match_name (st_parameter_dt *dtp, co for (i = 0; i < len; i++) { c = next_char (dtp); - if (c == EOF || (tolower (c) != tolower (name[i]))) + if (c == EOF || (tolower (c) != tolower ((unsigned char)name[i]))) { dtp->u.p.nml_read_error = 1; break; --- libgfortran/io/read.c +++ /tmp/cocci-output-7054-209e45-read.c @@ -947,7 +947,7 @@ read_f (st_parameter_dt *dtp, const fnod between "NaN" and the optional perenthesis is not permitted. */ while (w > 0) { - *out = tolower (*p); + *out = tolower ((unsigned char)*p); switch (*p) { case ' ': @@ -969,7 +969,7 @@ read_f (st_parameter_dt *dtp, const fnod goto bad_float; break; default: - if (!isalnum (*out)) + if (!isalnum ((unsigned char)*out)) goto bad_float; } --w; @@ -1091,7 +1091,7 @@ exponent: if (dtp->u.p.blank_status == BLANK_UNSPECIFIED) { - while (w > 0 && isdigit (*p)) + while (w > 0 && isdigit ((unsigned char)*p)) { exponent *= 10; exponent += *p - '0'; @@ -1119,7 +1119,7 @@ exponent: else assert (dtp->u.p.blank_status == BLANK_NULL); } - else if (!isdigit (*p)) + else if (!isdigit ((unsigned char)*p)) goto bad_float; else { --- libgfortran/io/format.c +++ /tmp/cocci-output-16280-1f8fd7-format.c @@ -194,7 +194,7 @@ next_char (format_data *fmt, int literal return -1; fmt->format_string_len--; - c = toupper (*fmt->format_string++); + c = toupper ((unsigned char)*fmt->format_string++); fmt->error_element = c; } while ((c == ' ' || c == '\t') && !literal); --- libgo/go/regexp/testdata/testregex.c +++ /tmp/cocci-output-11909-272cb0-testregex.c @@ -1267,7 +1267,7 @@ main(int argc, char** argv) state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2; p = unit; version = (char*)id + 10; - while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p)) + while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace((unsigned char)*p)) p++; *p = 0; while ((p = *++argv) && *p == '-') @@ -1452,7 +1452,7 @@ main(int argc, char** argv) /* parse: */ line = p; - if (*p == ':' && !isspace(*(p + 1))) + if (*p == ':' && !isspace((unsigned char)*(p + 1))) { while (*++p && *p != ':'); if (!*p++) @@ -1462,7 +1462,7 @@ main(int argc, char** argv) continue; } } - while (isspace(*p)) + while (isspace((unsigned char)*p)) p++; if (*p == 0 || *p == '#' || *p == 'T') { @@ -1476,8 +1476,8 @@ main(int argc, char** argv) printf("%s\n", line); else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) { - while (*++p && !isspace(*p)); - while (isspace(*p)) + while (*++p && !isspace((unsigned char)*p)); + while (isspace((unsigned char)*p)) p++; printf("NOTE %s\n", p); } @@ -1533,7 +1533,7 @@ main(int argc, char** argv) nsub = -1; for (p = spec; *p; p++) { - if (isdigit(*p)) + if (isdigit((unsigned char)*p)) { nmatch = strtol(p, &p, 10); if (nmatch >= elementsof(match)) --- libiberty/pex-win32.c +++ /tmp/cocci-output-25924-3a75ca-pex-win32.c @@ -547,8 +547,8 @@ env_compare (const void *a_ptr, const vo do { - c1 = (unsigned char) tolower (*a++); - c2 = (unsigned char) tolower (*b++); + c1 = (unsigned char) tolower ((unsigned char)*a++); + c2 = (unsigned char) tolower ((unsigned char)*b++); if (c1 == '=') c1 = '\0'; --- libobjc/gc.c +++ /tmp/cocci-output-2585-fc246d-gc.c @@ -68,7 +68,7 @@ __objc_gc_setup_array (GC_bitmap mask, c { int i, len = atoi (type + 1); - while (isdigit (*++type)) + while (isdigit ((unsigned char)*++type)) /* do nothing */; /* skip the size of the array */ switch (*type) { --- libquadmath/printf/quadmath-printf.c +++ /tmp/cocci-output-27535-6b9ccc-quadmath-printf.c @@ -189,7 +189,7 @@ quadmath_snprintf (char *str, size_t siz ++format; info.width = va_arg (ap, int); } - else if (isdigit (*format)) + else if (isdigit ((unsigned char)*format)) /* Constant width specification. */ info.width = read_int (&format); @@ -206,7 +206,7 @@ quadmath_snprintf (char *str, size_t siz info.prec = va_arg (ap, int); } - else if (isdigit (*format)) + else if (isdigit ((unsigned char)*format)) info.prec = read_int (&format); else /* "%.?" is treated like "%.0?". */ --- libquadmath/printf/printf_fphex.c +++ /tmp/cocci-output-25463-ffa004-printf_fphex.c @@ -169,7 +169,7 @@ __quadmath_printf_fphex (struct __quadma if (isnanq (fpnum.value)) { negative = fpnum.ieee.negative != 0; - if (isupper (info->spec)) + if (isupper ((unsigned char)info->spec)) { special = "NAN"; wspecial = L_("NAN"); @@ -184,7 +184,7 @@ __quadmath_printf_fphex (struct __quadma { if (isinfq (fpnum.value)) { - if (isupper (info->spec)) + if (isupper ((unsigned char)info->spec)) { special = "INF"; wspecial = L_("INF"); @@ -363,7 +363,7 @@ __quadmath_printf_fphex (struct __quadma think about it! */ break; } - else if (tolower (ch) < 'f') + else if (tolower ((unsigned char)ch) < 'f') { ++numstr[cnt]; ++wnumstr[cnt]; @@ -382,7 +382,7 @@ __quadmath_printf_fphex (struct __quadma get an overflow. */ if (leading == '9') leading = info->spec; - else if (tolower (leading) < 'f') + else if (tolower ((unsigned char)leading) < 'f') ++leading; else {