Skip to content

Commit

Permalink
Fix many calls to ctype functions
Browse files Browse the repository at this point in the history
All ctype functions like `isspace()`, `tolower()` and alike expect a
character as an `unsigned char` or EOF, anything else has undefined
behavior.

This commit should fix all calls to the various ctype functions either:

* adding `unsigned char` cast where appropriate;
* removing useless `int` casts that are more confusing than useful.

Some instances required slightly more involved changes though, but the
fix itself is the same.

To find the calls to check, I used an equivalent to the following:

```
git grep -P 'is(alnum|alpha|cntrl|x?digit|graph|lower|print|punct|'\
'space|upper|ascii|blank)|to(low|up)er'
```

...and then proceeded to manually check each one of them to see if the
call, or call chain, was using appropriate values and types.
  • Loading branch information
b4n committed May 25, 2023
1 parent 979433d commit 44dd85b
Show file tree
Hide file tree
Showing 53 changed files with 380 additions and 347 deletions.
2 changes: 1 addition & 1 deletion Units/simple-diff.d/input.diff
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ index 0000000..a1bf5f3
+ if (strncmp ((const char*) cp, DiffDelims[delim], 4u) == 0)
+ {
+ cp += 4;
+ if (isspace ((int) *cp)) continue;
+ if (isspace (*cp)) continue;
+ /* when original filename is /dev/null use the new one instead */
+ if (delim == DIFF_DELIM_MINUS &&
+ strncmp ((const char*) cp, "/dev/null", 9u) == 0 &&
Expand Down
2 changes: 1 addition & 1 deletion dsl/dsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ static EsObject* caseop (EsObject *o, int (*op)(int))
char *r = strdup (s);

for (char *tmp = r; *tmp != '\0'; tmp++)
*tmp = op (*tmp);
*tmp = op ((unsigned char) *tmp);

EsObject *q = es_object_autounref (es_string_new (r));
free (r);
Expand Down
2 changes: 1 addition & 1 deletion dsl/optscript.c
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ name_or_number_new (const char* s, void *data)
const char *t = s;
while (*t)
{
if (!isdigit ((int)*t))
if (!isdigit ((unsigned char) *t))
{
number = false;
break;
Expand Down
39 changes: 21 additions & 18 deletions libreadtags/readtags.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ static int readtags_fseek(FILE *fp, rt_off_t pos, int whence)
}

/* Converts a hexadecimal digit to its value */
static int xdigitValue (char digit)
static int xdigitValue (unsigned char digit)
{
if (digit >= '0' && digit <= '9')
return digit - '0';
Expand All @@ -151,39 +151,42 @@ static int xdigitValue (char digit)
* Reads the first character from the string, possibly un-escaping it, and
* advances *s to the start of the next character.
*/
static int readTagCharacter (const char **s)
static int readTagCharacter (const char **const s)
{
int c = **(const unsigned char **)s;
const unsigned char *p = (const unsigned char *) *s;
int c = *p;

(*s)++;
p++;

if (c == '\\')
{
switch (**s)
switch (*p)
{
case 't': c = '\t'; (*s)++; break;
case 'r': c = '\r'; (*s)++; break;
case 'n': c = '\n'; (*s)++; break;
case '\\': c = '\\'; (*s)++; break;
case 't': c = '\t'; p++; break;
case 'r': c = '\r'; p++; break;
case 'n': c = '\n'; p++; break;
case '\\': c = '\\'; p++; break;
/* Universal-CTags extensions */
case 'a': c = '\a'; (*s)++; break;
case 'b': c = '\b'; (*s)++; break;
case 'v': c = '\v'; (*s)++; break;
case 'f': c = '\f'; (*s)++; break;
case 'a': c = '\a'; p++; break;
case 'b': c = '\b'; p++; break;
case 'v': c = '\v'; p++; break;
case 'f': c = '\f'; p++; break;
case 'x':
if (isxdigit ((*s)[1]) && isxdigit ((*s)[2]))
if (isxdigit (p[1]) && isxdigit (p[2]))
{
int val = (xdigitValue ((*s)[1]) << 4) | xdigitValue ((*s)[2]);
int val = (xdigitValue (p[1]) << 4) | xdigitValue (p[2]);
if (val < 0x80)
{
(*s) += 3;
p += 3;
c = val;
}
}
break;
}
}

*s = (const char *) p;

return c;
}

Expand Down Expand Up @@ -610,12 +613,12 @@ static tagResult parseTagLine (tagFile *file, tagEntry *const entry, int *err)
else
++p;
}
else if (isdigit ((int) *(unsigned char*) p))
else if (isdigit (*(unsigned char*) p))
{
/* parse line number */
entry->address.pattern = p;
entry->address.lineNumber = atol (p);
while (isdigit ((int) *(unsigned char*) p))
while (isdigit (*(unsigned char*) p))
++p;
if (p)
{
Expand Down
6 changes: 3 additions & 3 deletions main/args.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static char *nextStringArg (const char** const next)
const char* start;

Assert (*next != NULL);
for (start = *next ; isspace ((int) *start) ; ++start)
for (start = *next ; isspace ((unsigned char) *start) ; ++start)
;
if (*start == '\0')
*next = start;
Expand All @@ -40,7 +40,7 @@ static char *nextStringArg (const char** const next)
size_t length;
const char* end;

for (end = start ; *end != '\0' && ! isspace ((int) *end) ; ++end)
for (end = start; *end != '\0' && ! isspace ((unsigned char) *end); ++end)
;
length = end - start;
Assert (length > 0);
Expand Down Expand Up @@ -156,7 +156,7 @@ static char* nextFileLine (FILE* const fp)

static bool isCommentLine (char* line)
{
while (isspace(*line))
while (isspace((unsigned char) *line))
++line;
return (*line == '#');
}
Expand Down
4 changes: 2 additions & 2 deletions main/field.c
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ static const char* renderCompactInputLine (vString *b, const char *const line)

/* Consume repeating white space.
*/
while (next = *(p+1) , isspace (next) && next != NEWLINE)
while (next = (unsigned char) *(p+1), isspace (next) && next != NEWLINE)
++p;
c = ' '; /* force space character for any white space */
}
Expand Down Expand Up @@ -1328,7 +1328,7 @@ extern int defineField (fieldDefinition *def, langType language)
Assert (def->name);
for (i = 0; i < strlen (def->name); i++)
{
Assert ( isalpha (def->name [i]) );
Assert ( isalpha ((unsigned char) def->name [i]) );
}
def->letter = NUL_FIELD_LETTER;

Expand Down
8 changes: 4 additions & 4 deletions main/keyword.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,17 @@ static hashEntry *getHashTableEntry (unsigned long hashedValue)
static unsigned int hashValue (const char *const string, langType language,
unsigned int maxLen, bool *maxLenReached)
{
const signed char *p;
const char *p;
unsigned int h = 5381;

Assert (string != NULL);

/* "djb" hash as used in g_str_hash() in glib */
for (p = (const signed char *)string; *p != '\0'; p++)
for (p = string; *p != '\0'; p++)
{
h = (h << 5) + h + tolower (*p);
h = (h << 5) + h + (signed char) tolower ((unsigned char) *p);

if (p > (const signed char *)string + maxLen)
if (p > string + maxLen)
{
*maxLenReached = true;
return 0;
Expand Down
2 changes: 1 addition & 1 deletion main/kind.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static void initRoleObject (roleObject *robj, roleDefinition *rdef, freeRoleDefF
#ifdef DEBUG
size_t len = strlen (rdef->name);
for (int i = 0; i < len; i++)
Assert (isalnum (rdef->name [i]));
Assert (isalnum ((unsigned char) rdef->name [i]));
#endif
robj->def = rdef;
robj->free = freefunc;
Expand Down
14 changes: 7 additions & 7 deletions main/lregex.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ static void pre_ptrn_flag_guest_long (const char* const s, const char* const v,
{
const char *n_tmp = v + 1;
const char *n = n_tmp;
for (; isdigit (*n_tmp); n_tmp++);
for (; isdigit ((unsigned char) *n_tmp); n_tmp++);
char c = *n_tmp;
*(char *)n_tmp = '\0';
if (!strToInt (n, 10, &(guest->lang.spec.patternGroup)))
Expand Down Expand Up @@ -886,7 +886,7 @@ static void pre_ptrn_flag_guest_long (const char* const s, const char* const v,
{
char *n = tmp;

for (; isdigit (*tmp); tmp++);
for (; isdigit ((unsigned char) *tmp); tmp++);
char c = *tmp;
*tmp = '\0';
if (!strToInt (n, 10, &(current->patternGroup)))
Expand Down Expand Up @@ -1599,7 +1599,7 @@ static vString* substitute (
const char* p;
for (p = out ; *p != '\0' ; p++)
{
if (*p == '\\' && isdigit ((int) *++p))
if (*p == '\\' && isdigit ((unsigned char) *++p))
{
const int dig = *p - '0';
if (0 < dig && dig < nmatch && pmatch [dig].rm_so != -1)
Expand Down Expand Up @@ -2294,7 +2294,7 @@ static regexPattern *addTagRegexInternal (struct lregexControlBlock *lcb,
{
if (p == kindName)
{
if (!isalpha(*p))
if (!isalpha((unsigned char) *p))
error (FATAL,
"A kind name doesn't start with an alphabetical character: "
"'%s' in \"--%s-%s\" option",
Expand All @@ -2310,7 +2310,7 @@ static regexPattern *addTagRegexInternal (struct lregexControlBlock *lcb,
* in which Exuberant-ctags users define kind names with whitespaces.
* "FATAL" error breaks the compatibility.
*/
if (!isalnum(*p))
if (!isalnum((unsigned char) *p))
error (/* regptype == REG_PARSER_SINGLE_LINE? WARNING: */ FATAL,
"Non-alphanumeric char is used in kind name: "
"'%s' in \"--%s-%s\" option",
Expand Down Expand Up @@ -2433,7 +2433,7 @@ static void addTagRegexOption (struct lregexControlBlock *lcb,
const char *c;
for (c = pattern; *c; c++)
{
if (! (isalnum(*c) || *c == '_'))
if (! (isalnum((unsigned char) *c) || *c == '_'))
{
if (*c && (*(c + 1) != '^'))
{
Expand Down Expand Up @@ -2652,7 +2652,7 @@ extern void addRegexTable (struct lregexControlBlock *lcb, const char *name)
{
const char *c;
for (c = name; *c; c++)
if (! (isalnum(*c) || *c == '_'))
if (! (isalnum((unsigned char) *c) || *c == '_'))
error (FATAL, "`%c' in \"%s\" is not acceptable as part of table name", *c, name);

if (getTableIndexForName(lcb, name) >= 0)
Expand Down
2 changes: 1 addition & 1 deletion main/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -2604,7 +2604,7 @@ static void processIgnoreOption (const char *const list, int IgnoreOrDefine)
addIgnoreListFromFile (lang, fileName);
}
#if defined (WIN32)
else if (isalpha (list [0]) && list [1] == ':')
else if (isalpha ((unsigned char) list [0]) && list [1] == ':')
addIgnoreListFromFile (lang, list);
#endif
else if (strcmp (list, "-") == 0)
Expand Down
Loading

0 comments on commit 44dd85b

Please sign in to comment.