Hi, everyone. I've been auditing the OpenBSD codebase for calls to ctype functions with potentially signed chars. This is undefined on some platforms. I found a number of instances in Sqlite, so I ran my Coccinelle script on the repo.
The below diff was generated automatically, so formatting may be changed and mistakes are possible (though unlikely). Here's the relevant CERT entry: https://www.securecoding.cert.org/confluence/display/c/STR37-C.+Arguments+to+character-handling+functions+must+be+representable+as+an+unsigned+char Let me know what you think. Thanks, Michael Index: autoconf/tea/win/nmakehlp.c ================================================================== --- autoconf/tea/win/nmakehlp.c +++ autoconf/tea/win/nmakehlp.c @@ -603,15 +603,15 @@ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { char *ks, *ke, *vs, *ve; ks = szBuffer; - while (ks && *ks && isspace(*ks)) ++ks; + while (ks && *ks && isspace((unsigned char)*ks)) ++ks; ke = ks; - while (ke && *ke && !isspace(*ke)) ++ke; + while (ke && *ke && !isspace((unsigned char)*ke)) ++ke; vs = ke; - while (vs && *vs && isspace(*vs)) ++vs; + while (vs && *vs && isspace((unsigned char)*vs)) ++vs; ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; list_insert(&substPtr, ks, vs); } Index: ext/fts1/fts1.c ================================================================== --- ext/fts1/fts1.c +++ ext/fts1/fts1.c @@ -203,17 +203,17 @@ ** tokenizer-generated tokens rather than doing its own local ** tokenization. */ /* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ static int safe_isspace(char c){ - return (c&0x80)==0 ? isspace(c) : 0; + return (c&0x80)==0 ? isspace((unsigned char)c) : 0; } static int safe_tolower(char c){ - return (c&0x80)==0 ? tolower(c) : c; + return (c&0x80)==0 ? tolower((unsigned char)c) : c; } static int safe_isalnum(char c){ - return (c&0x80)==0 ? isalnum(c) : 0; + return (c&0x80)==0 ? isalnum((unsigned char)c) : 0; } typedef enum DocListType { DL_DOCIDS, /* docids only */ DL_POSITIONS, /* docids + positions */ Index: ext/fts1/simple_tokenizer.c ================================================================== --- ext/fts1/simple_tokenizer.c +++ ext/fts1/simple_tokenizer.c @@ -136,11 +136,11 @@ for(ii=0; ii<n; ii++){ /* TODO(shess) This needs expansion to handle UTF-8 ** case-insensitivity. */ char ch = c->pCurrent[ii]; - c->zToken[ii] = (unsigned char)ch<0x80 ? tolower(ch) : ch; + c->zToken[ii] = (unsigned char)ch<0x80 ? tolower((unsigned char)ch) : ch; } c->zToken[n] = '\0'; *ppToken = c->zToken; *pnBytes = n; *piStartOffset = (int) (c->pCurrent-c->pInput); Index: ext/misc/amatch.c ================================================================== --- ext/misc/amatch.c +++ ext/misc/amatch.c @@ -814,14 +814,14 @@ int nKey = (int)strlen(zKey); int nStr = (int)strlen(zStr); int i; if( nStr<nKey+1 ) return 0; if( memcmp(zStr, zKey, nKey)!=0 ) return 0; - for(i=nKey; isspace(zStr[i]); i++){} + for(i=nKey; isspace((unsigned char)zStr[i]); i++){} if( zStr[i]!='=' ) return 0; i++; - while( isspace(zStr[i]) ){ i++; } + while( isspace((unsigned char)zStr[i]) ){ i++; } return zStr+i; } /* ** xConnect/xCreate method for the amatch module. Arguments are: Index: ext/misc/closure.c ================================================================== --- ext/misc/closure.c +++ ext/misc/closure.c @@ -484,14 +484,14 @@ int nKey = (int)strlen(zKey); int nStr = (int)strlen(zStr); int i; if( nStr<nKey+1 ) return 0; if( memcmp(zStr, zKey, nKey)!=0 ) return 0; - for(i=nKey; isspace(zStr[i]); i++){} + for(i=nKey; isspace((unsigned char)zStr[i]); i++){} if( zStr[i]!='=' ) return 0; i++; - while( isspace(zStr[i]) ){ i++; } + while( isspace((unsigned char)zStr[i]) ){ i++; } return zStr+i; } /* ** xConnect/xCreate method for the closure module. Arguments are: Index: ext/misc/spellfix.c ================================================================== --- ext/misc/spellfix.c +++ ext/misc/spellfix.c @@ -1849,11 +1849,11 @@ */ static char *spellfix1Dequote(const char *zIn){ char *zOut; int i, j; char c; - while( isspace(zIn[0]) ) zIn++; + while( isspace((unsigned char)zIn[0]) ) zIn++; zOut = sqlite3_mprintf("%s", zIn); if( zOut==0 ) return 0; i = (int)strlen(zOut); #if 0 /* The parser will never leave spaces at the end */ while( i>0 && isspace(zOut[i-1]) ){ i--; } Index: mptest/mptest.c ================================================================== --- mptest/mptest.c +++ mptest/mptest.c @@ -185,14 +185,14 @@ } c2 = *(zGlob++); } if( c2==0 || (seen ^ invert)==0 ) return 0; }else if( c=='#' ){ - if( (z[0]=='-' || z[0]=='+') && isdigit(z[1]) ) z++; - if( !isdigit(z[0]) ) return 0; + if( (z[0]=='-' || z[0]=='+') && isdigit((unsigned char)z[1]) ) z++; + if( !isdigit((unsigned char)z[0]) ) return 0; z++; - while( isdigit(z[0]) ){ z++; } + while( isdigit((unsigned char)z[0]) ){ z++; } }else{ if( c!=(*(z++)) ) return 0; } } return *z==0; @@ -287,11 +287,11 @@ /* ** Return the length of a string omitting trailing whitespace */ static int clipLength(const char *z){ int n = (int)strlen(z); - while( n>0 && isspace(z[n-1]) ){ n--; } + while( n>0 && isspace((unsigned char)z[n - 1]) ){ n--; } return n; } /* ** Auxiliary SQL function to return the name of the VFS @@ -442,11 +442,11 @@ if( p->n ) stringAppend(p, " ", 1); if( z==0 ){ stringAppend(p, "nil", 3); return; } - for(i=0; z[i] && !isspace(z[i]); i++){} + for(i=0; z[i] && !isspace((unsigned char)z[i]); i++){} if( i>0 && z[i]==0 ){ stringAppend(p, z, i); return; } stringAppend(p, "'", 1); @@ -697,11 +697,11 @@ /* ** Return the length of the next token. */ static int tokenLength(const char *z, int *pnLine){ int n = 0; - if( isspace(z[0]) || (z[0]=='/' && z[1]=='*') ){ + if( isspace((unsigned char)z[0]) || (z[0]=='/' && z[1]=='*') ){ int inC = 0; int c; if( z[0]=='/' ){ inC = 1; n = 2; @@ -746,21 +746,21 @@ int i; if( nIn<=0 ){ zOut[0] = 0; return 0; } - for(i=0; i<nIn && i<nOut-1 && !isspace(zIn[i]); i++){ zOut[i] = zIn[i]; } + for(i=0; i<nIn && i<nOut-1 && !isspace((unsigned char)zIn[i]); i++){ zOut[i] = zIn[i]; } zOut[i] = 0; return i; } /* ** Find the number of characters up to the start of the next "--end" token. */ static int findEnd(const char *z, int *pnLine){ int n = 0; - while( z[n] && (strncmp(z+n,"--end",5) || !isspace(z[n+5])) ){ + while( z[n] && (strncmp(z+n,"--end",5) || !isspace((unsigned char)z[n + 5])) ){ n += tokenLength(z+n, pnLine); } return n; } @@ -771,16 +771,16 @@ */ static int findEndif(const char *z, int stopAtElse, int *pnLine){ int n = 0; while( z[n] ){ int len = tokenLength(z+n, pnLine); - if( (strncmp(z+n,"--endif",7)==0 && isspace(z[n+7])) - || (stopAtElse && strncmp(z+n,"--else",6)==0 && isspace(z[n+6])) + if( (strncmp(z+n,"--endif",7)==0 && isspace((unsigned char)z[n + 7])) + || (stopAtElse && strncmp(z+n,"--else",6)==0 && isspace((unsigned char)z[n + 6])) ){ return n+len; } - if( strncmp(z+n,"--if",4)==0 && isspace(z[n+4]) ){ + if( strncmp(z+n,"--if",4)==0 && isspace((unsigned char)z[n + 4]) ){ int skip = findEndif(z+n+len, 0, pnLine); n += skip + len; }else{ n += len; } @@ -890,11 +890,11 @@ len = tokenLength(zScript+ii, &lineno); if( isspace(c) || (c=='/' && zScript[ii+1]=='*') ){ ii += len; continue; } - if( c!='-' || zScript[ii+1]!='-' || !isalpha(zScript[ii+2]) ){ + if( c!='-' || zScript[ii+1]!='-' || !isalpha((unsigned char)zScript[ii + 2]) ){ ii += len; continue; } /* Run any prior SQL before processing the new --command */ @@ -907,11 +907,11 @@ /* Parse the --command */ if( g.iTrace>=2 ) logMessage("%.*s", len, zScript+ii); n = extractToken(zScript+ii+2, len-2, zCmd, sizeof(zCmd)); for(nArg=0; n<len-2 && nArg<MX_ARG; nArg++){ - while( n<len-2 && isspace(zScript[ii+2+n]) ){ n++; } + while( n<len-2 && isspace((unsigned char)zScript[ii + 2 + n]) ){ n++; } if( n>=len-2 ) break; n += extractToken(zScript+ii+2+n, len-2-n, azArg[nArg], sizeof(azArg[nArg])); } for(j=nArg; j<MX_ARG; j++) azArg[j++][0] = 0; @@ -974,11 +974,11 @@ ** Check to see if output matches ANSWER. Report an error if not. */ if( strcmp(zCmd, "match")==0 ){ int jj; char *zAns = zScript+ii; - for(jj=7; jj<len-1 && isspace(zAns[jj]); jj++){} + for(jj=7; jj<len-1 && isspace((unsigned char)zAns[jj]); jj++){} zAns += jj; if( len-jj-1!=sResult.n || strncmp(sResult.z, zAns, len-jj-1) ){ errorMessage("line %d of %s:\nExpected [%.*s]\n Got [%s]", prevLine, zFilename, len-jj-1, zAns, sResult.z); } @@ -996,11 +996,11 @@ if( strcmp(zCmd, "glob")==0 || strcmp(zCmd, "notglob")==0 ){ int jj; char *zAns = zScript+ii; char *zCopy; int isGlob = (zCmd[0]=='g'); - for(jj=9-3*isGlob; jj<len-1 && isspace(zAns[jj]); jj++){} + for(jj=9-3*isGlob; jj<len-1 && isspace((unsigned char)zAns[jj]); jj++){} zAns += jj; zCopy = sqlite3_mprintf("%.*s", len-jj-1, zAns); if( (sqlite3_strglob(zCopy, sResult.z)==0)^isGlob ){ errorMessage("line %d of %s:\nExpected [%s]\n Got [%s]", prevLine, zFilename, zCopy, sResult.z); @@ -1048,11 +1048,11 @@ ** ** Output the remainder of the line to the log file */ if( strcmp(zCmd, "print")==0 ){ int jj; - for(jj=7; jj<len && isspace(zScript[ii+jj]); jj++){} + for(jj=7; jj<len && isspace((unsigned char)zScript[ii + jj]); jj++){} logMessage("%.*s", len-jj, zScript+ii+jj); }else /* ** --if EXPR @@ -1060,11 +1060,11 @@ ** Skip forward to the next matching --endif or --else if EXPR is false. */ if( strcmp(zCmd, "if")==0 ){ int jj, rc; sqlite3_stmt *pStmt; - for(jj=4; jj<len && isspace(zScript[ii+jj]); jj++){} + for(jj=4; jj<len && isspace((unsigned char)zScript[ii + jj]); jj++){} pStmt = prepareSql("SELECT %.*s", len-jj, zScript+ii+jj); rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW || sqlite3_column_int(pStmt, 0)==0 ){ ii += findEndif(zScript+ii+len, 1, &lineno); } Index: test/fuzzcheck.c ================================================================== --- test/fuzzcheck.c +++ test/fuzzcheck.c @@ -631,13 +631,13 @@ sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore); if( zMore==zSql ) break; if( runFlags & SQL_TRACE ){ const char *z = zSql; int n; - while( z<zMore && isspace(z[0]) ) z++; + while( z<zMore && isspace((unsigned char)z[0]) ) z++; n = (int)(zMore - z); - while( n>0 && isspace(z[n-1]) ) n--; + while( n>0 && isspace((unsigned char)z[n - 1]) ) n--; if( n==0 ) break; if( pStmt==0 ){ printf("TRACE: %.*s (error: %s)\n", n, z, sqlite3_errmsg(db)); }else{ printf("TRACE: %.*s\n", n, z); @@ -755,11 +755,11 @@ while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ - while( isdigit(zArg[0]) ){ + while( isdigit((unsigned char)zArg[0]) ){ v = v*10 + zArg[0] - '0'; zArg++; } } for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){ Index: test/speedtest1.c ================================================================== --- test/speedtest1.c +++ test/speedtest1.c @@ -133,11 +133,11 @@ while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ - while( isdigit(zArg[0]) ){ + while( isdigit((unsigned char)zArg[0]) ){ v = v*10 + zArg[0] - '0'; zArg++; } } for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){ @@ -313,11 +313,11 @@ } /* Print an SQL statement to standard output */ static void printSql(const char *zSql){ int n = (int)strlen(zSql); - while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; } + while( n>0 && (zSql[n-1]==';' || isspace((unsigned char)zSql[n - 1])) ){ n--; } if( g.bExplain ) printf("EXPLAIN "); printf("%.*s;\n", n, zSql); if( g.bExplain #if SQLITE_VERSION_NUMBER>=3007017 && ( sqlite3_strglob("CREATE *", zSql)==0 @@ -412,11 +412,11 @@ } /* The sqlite3_trace() callback function */ static void traceCallback(void *NotUsed, const char *zSql){ int n = (int)strlen(zSql); - while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ) n--; + while( n>0 && (zSql[n-1]==';' || isspace((unsigned char)zSql[n - 1])) ) n--; fprintf(stderr,"%.*s;\n", n, zSql); } /* Substitute random() function that gives the same random ** sequence on each run, for repeatability. */ Index: test/wordcount.c ================================================================== --- test/wordcount.c +++ test/wordcount.c @@ -390,12 +390,12 @@ } /* Process the input file */ while( fgets(zInput, sizeof(zInput), in) ){ for(i=0; zInput[i]; i++){ - if( !isalpha(zInput[i]) ) continue; - for(j=i+1; isalpha(zInput[j]); j++){} + if( !isalpha((unsigned char)zInput[i]) ) continue; + for(j=i+1; isalpha((unsigned char)zInput[j]); j++){} /* Found a new word at zInput[i] that is j-i bytes long. ** Process it into the wordcount table. */ if( iMode==MODE_DELETE ){ sqlite3_bind_text(pDelete, 1, zInput+i, j-i, SQLITE_STATIC); Index: tool/fuzzershell.c ================================================================== --- tool/fuzzershell.c +++ tool/fuzzershell.c @@ -381,11 +381,11 @@ while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ - while( isdigit(zArg[0]) ){ + while( isdigit((unsigned char)zArg[0]) ){ v = v*10 + zArg[0] - '0'; zArg++; } } for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){ Index: tool/lemon.c ================================================================== --- tool/lemon.c +++ tool/lemon.c @@ -91,13 +91,13 @@ for(i=j=0; (c = zFormat[i])!=0; i++){ if( c=='%' ){ int iWidth = 0; lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); c = zFormat[++i]; - if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){ + if( isdigit(c) || (c=='-' && isdigit((unsigned char)zFormat[i + 1])) ){ if( c=='-' ) i++; - while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; + while( isdigit((unsigned char)zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; if( c=='-' ) iWidth = -iWidth; c = zFormat[i]; } if( c=='d' ){ int v = va_arg(ap, int); @@ -1576,11 +1576,11 @@ qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); lem.nsymbol = i - 1; - for(i=1; isupper(lem.symbols[i]->name[0]); i++); + for(i=1; isupper((unsigned char)lem.symbols[i]->name[0]); i++); lem.nterminal = i; /* Generate a reprint of the grammar, if requested on the command line */ if( rpflag ){ Reprint(&lem); @@ -2119,11 +2119,11 @@ psp->gp->nrule = 0; /* Fall thru to next case */ case WAITING_FOR_DECL_OR_RULE: if( x[0]=='%' ){ psp->state = WAITING_FOR_DECL_KEYWORD; - }else if( islower(x[0]) ){ + }else if( islower((unsigned char)x[0]) ){ psp->lhs = Symbol_new(x); psp->nrhs = 0; psp->lhsalias = 0; psp->state = WAITING_FOR_ARROW; }else if( x[0]=='{' ){ @@ -2149,11 +2149,11 @@ x); psp->errorcnt++; } break; case PRECEDENCE_MARK_1: - if( !isupper(x[0]) ){ + if( !isupper((unsigned char)x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "The precedence symbol must be a terminal."); psp->errorcnt++; }else if( psp->prevrule==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, @@ -2189,11 +2189,11 @@ psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case LHS_ALIAS_1: - if( isalpha(x[0]) ){ + if( isalpha((unsigned char)x[0]) ){ psp->lhsalias = x; psp->state = LHS_ALIAS_2; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "\"%s\" is not a valid alias for the LHS \"%s\"\n", @@ -2258,11 +2258,11 @@ psp->lastrule = rp; } psp->prevrule = rp; } psp->state = WAITING_FOR_DECL_OR_RULE; - }else if( isalpha(x[0]) ){ + }else if( isalpha((unsigned char)x[0]) ){ if( psp->nrhs>=MAXRHS ){ ErrorMsg(psp->filename,psp->tokenlineno, "Too many symbols on RHS of rule beginning at \"%s\".", x); psp->errorcnt++; @@ -2287,11 +2287,11 @@ } msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); - if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){ + if( islower((unsigned char)x[1]) || islower((unsigned char)msp->subsym[0]->name[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Cannot form a compound containing a non-terminal"); psp->errorcnt++; } }else if( x[0]=='(' && psp->nrhs>0 ){ @@ -2302,11 +2302,11 @@ psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case RHS_ALIAS_1: - if( isalpha(x[0]) ){ + if( isalpha((unsigned char)x[0]) ){ psp->alias[psp->nrhs-1] = x; psp->state = RHS_ALIAS_2; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n", @@ -2324,11 +2324,11 @@ psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case WAITING_FOR_DECL_KEYWORD: - if( isalpha(x[0]) ){ + if( isalpha((unsigned char)x[0]) ){ psp->declkeyword = x; psp->declargslot = 0; psp->decllinenoslot = 0; psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; @@ -2404,11 +2404,11 @@ psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_DESTRUCTOR_SYMBOL: - if( !isalpha(x[0]) ){ + if( !isalpha((unsigned char)x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol name missing after %%destructor keyword"); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ @@ -2418,11 +2418,11 @@ psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; } break; case WAITING_FOR_DATATYPE_SYMBOL: - if( !isalpha(x[0]) ){ + if( !isalpha((unsigned char)x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol name missing after %%type keyword"); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ @@ -2443,11 +2443,11 @@ } break; case WAITING_FOR_PRECEDENCE_SYMBOL: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; - }else if( isupper(x[0]) ){ + }else if( isupper((unsigned char)x[0]) ){ struct symbol *sp; sp = Symbol_new(x); if( sp->prec>=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol \"%s\" has already be given a precedence.",x); @@ -2461,11 +2461,11 @@ "Can't assign a precedence to \"%s\".",x); psp->errorcnt++; } break; case WAITING_FOR_DECL_ARG: - if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ + if( x[0]=='{' || x[0]=='\"' || isalnum((unsigned char)x[0]) ){ const char *zOld, *zNew; char *zBuf, *z; int nOld, n, nLine = 0, nNew, nBack; int addLineMacro; char zLine[50]; @@ -2522,11 +2522,11 @@ } break; case WAITING_FOR_FALLBACK_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; - }else if( !isupper(x[0]) ){ + }else if( !isupper((unsigned char)x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%fallback argument \"%s\" should be a token", x); psp->errorcnt++; }else{ struct symbol *sp = Symbol_new(x); @@ -2543,11 +2543,11 @@ } break; case WAITING_FOR_WILDCARD_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; - }else if( !isupper(x[0]) ){ + }else if( !isupper((unsigned char)x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%wildcard argument \"%s\" should be a token", x); psp->errorcnt++; }else{ struct symbol *sp = Symbol_new(x); @@ -2559,11 +2559,11 @@ psp->errorcnt++; } } break; case WAITING_FOR_CLASS_ID: - if( !islower(x[0]) ){ + if( !islower((unsigned char)x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%token_class must be followed by an identifier: ", x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else if( Symbol_find(x) ){ @@ -2578,16 +2578,16 @@ } break; case WAITING_FOR_CLASS_TOKEN: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; - }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){ + }else if( isupper((unsigned char)x[0]) || ((x[0]=='|' || x[0]=='/') && isupper((unsigned char)x[1])) ){ struct symbol *msp = psp->tkclass; msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); - if( !isupper(x[0]) ) x++; + if( !isupper((unsigned char)x[0]) ) x++; msp->subsym[msp->nsubsym-1] = Symbol_new(x); }else{ ErrorMsg(psp->filename, psp->tokenlineno, "%%token_class argument \"%s\" should be a token", x); psp->errorcnt++; @@ -2616,25 +2616,25 @@ int lineno = 1; int start_lineno = 1; for(i=0; z[i]; i++){ if( z[i]=='\n' ) lineno++; if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; - if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){ + if( strncmp(&z[i],"%endif",6)==0 && isspace((unsigned char)z[i + 6]) ){ if( exclude ){ exclude--; if( exclude==0 ){ for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' '; } } for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; - }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace(z[i+6])) - || (strncmp(&z[i],"%ifndef",7)==0 && isspace(z[i+7])) ){ + }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace((unsigned char)z[i + 6])) + || (strncmp(&z[i],"%ifndef",7)==0 && isspace((unsigned char)z[i + 7])) ){ if( exclude ){ exclude++; }else{ - for(j=i+7; isspace(z[j]); j++){} - for(n=0; z[j+n] && !isspace(z[j+n]); n++){} + for(j=i+7; isspace((unsigned char)z[j]); j++){} + for(n=0; z[j+n] && !isspace((unsigned char)z[j + n]); n++){} exclude = 1; for(k=0; k<nDefine; k++){ if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){ exclude = 0; break; @@ -2786,11 +2786,11 @@ while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++; nextcp = cp; }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */ cp += 3; nextcp = cp; - }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){ + }else if( (c=='/' || c=='|') && isalpha((unsigned char)cp[1]) ){ cp += 2; while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++; nextcp = cp; }else{ /* All other (one character) operators */ cp++; @@ -3239,11 +3239,11 @@ (*lineno)++; iStart = 0; if( name ){ for(i=0; line[i]; i++){ if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 - && (i==0 || !isalpha(line[i-1])) + && (i==0 || !isalpha((unsigned char)line[i - 1])) ){ if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]); fprintf(out,"%s",name); i += 4; iStart = i+1; @@ -3476,13 +3476,13 @@ append_str(0,0,0,0); /* This const cast is wrong but harmless, if we're careful. */ for(cp=(char *)rp->code; *cp; cp++){ - if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ + if( isalpha((unsigned char)*cp) && (cp==rp->code || (!isalnum((unsigned char)cp[-1]) && cp[-1]!='_')) ){ char saved; - for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); + for(xp= &cp[1]; isalnum((unsigned char)*xp) || *xp=='_'; xp++); saved = *xp; *xp = 0; if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); cp = xp; @@ -3643,13 +3643,13 @@ continue; } cp = sp->datatype; if( cp==0 ) cp = lemp->vartype; j = 0; - while( isspace(*cp) ) cp++; + while( isspace((unsigned char)*cp) ) cp++; while( *cp ) stddt[j++] = *cp++; - while( j>0 && isspace(stddt[j-1]) ) j--; + while( j>0 && isspace((unsigned char)stddt[j - 1]) ) j--; stddt[j] = 0; if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){ sp->dtnum = 0; continue; } @@ -3855,12 +3855,12 @@ fprintf(out,"#if INTERFACE\n"); lineno++; } name = lemp->name ? lemp->name : "Parse"; if( lemp->arg && lemp->arg[0] ){ i = lemonStrlen(lemp->arg); - while( i>=1 && isspace(lemp->arg[i-1]) ) i--; - while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; + while( i>=1 && isspace((unsigned char)lemp->arg[i - 1]) ) i--; + while( i>=1 && (isalnum((unsigned char)lemp->arg[i - 1]) || lemp->arg[i-1]=='_') ) i--; fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n", name,lemp->arg,&lemp->arg[i]); lineno++; fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n", @@ -4664,11 +4664,11 @@ sp = Symbol_find(x); if( sp==0 ){ sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); - sp->type = isupper(*x) ? TERMINAL : NONTERMINAL; + sp->type = isupper((unsigned char)*x) ? TERMINAL : NONTERMINAL; sp->rule = 0; sp->fallback = 0; sp->prec = -1; sp->assoc = UNK; sp->firstset = 0; Index: tool/showdb.c ================================================================== --- tool/showdb.c +++ tool/showdb.c @@ -651,15 +651,15 @@ while( zArgs[0] ){ switch( zArgs[0] ){ case 'c': showCellContent = 1; break; case 'm': showMap = 1; break; case 'd': { - if( !isdigit(zArgs[1]) ){ + if( !isdigit((unsigned char)zArgs[1]) ){ cellToDecode = -1; }else{ cellToDecode = 0; - while( isdigit(zArgs[1]) ){ + while( isdigit((unsigned char)zArgs[1]) ){ zArgs++; cellToDecode = cellToDecode*10 + zArgs[0] - '0'; } } break; @@ -1121,11 +1121,11 @@ } if( strcmp(azArg[i], "help")==0 ){ usage(zPrg); continue; } - if( !isdigit(azArg[i][0]) ){ + if( !isdigit((unsigned char)azArg[i][0]) ){ fprintf(stderr, "%s: unknown option: [%s]\n", zPrg, azArg[i]); continue; } iStart = strtol(azArg[i], &zLeft, 0); if( zLeft && strcmp(zLeft,"..end")==0 ){ Index: tool/showstat4.c ================================================================== --- tool/showstat4.c +++ tool/showstat4.c @@ -129,11 +129,11 @@ printf("'"); }else{ printf("%s\"", zSep); for(j=0; j<sz; j++){ char c = (char)aSample[y+j]; - if( isprint(c) ){ + if( isprint((unsigned char)c) ){ if( c=='"' || c=='\\' ) putchar('\\'); putchar(c); }else if( c=='\n' ){ printf("\\n"); }else if( c=='\t' ){ Index: tool/showwal.c ================================================================== --- tool/showwal.c +++ tool/showwal.c @@ -548,11 +548,11 @@ char *zLeft; if( strcmp(argv[i], "header")==0 ){ print_wal_header(0); continue; } - if( !isdigit(argv[i][0]) ){ + if( !isdigit((unsigned char)argv[i][0]) ){ fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]); continue; } iStart = strtol(argv[i], &zLeft, 0); if( zLeft && strcmp(zLeft,"..end")==0 ){ Index: tool/speedtest16.c ================================================================== --- tool/speedtest16.c +++ tool/speedtest16.c @@ -138,11 +138,11 @@ zSql[j+1] = 0; isComplete = sqlite3_complete(&zSql[i]); zSql[j+1] = c; if( isComplete ){ zSql[j] = 0; - while( i<j && isspace(zSql[i]) ){ i++; } + while( i<j && isspace((unsigned char)zSql[i]) ){ i++; } if( i<j ){ nStmt++; nByte += j-i; prepareAndRun(db, &zSql[i]); } Index: tool/speedtest8inst1.c ================================================================== --- tool/speedtest8inst1.c +++ tool/speedtest8inst1.c @@ -195,11 +195,11 @@ zSql[j+1] = 0; isComplete = sqlite3_complete(&zSql[i]); zSql[j+1] = c; if( isComplete ){ zSql[j] = 0; - while( i<j && isspace(zSql[i]) ){ i++; } + while( i<j && isspace((unsigned char)zSql[i]) ){ i++; } if( i<j ){ prepareAndRun(pInstVfs, db, &zSql[i]); } zSql[j] = ';'; i = j+1;