From 5e40c1ac011bf6289a35d66b610328f5e47e9536 Mon Sep 17 00:00:00 2001 From: Kevin Easton Date: Sun, 12 Nov 2017 22:43:20 +1100 Subject: [PATCH] Don't move pointer before start of object in move_word_rel() The old code could move the variable 'pointer' backwards one character before the start of the string (then incremented it again before returning). Formally this is undefined behaviour, so fix it. --- include/ircaux.h | 2 +- source/words.c | 52 +++++++++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/ircaux.h b/include/ircaux.h index 9793bcd..eff7e0b 100644 --- a/include/ircaux.h +++ b/include/ircaux.h @@ -134,7 +134,7 @@ char * base64_encode (const void *data, size_t size); #define EOS 32767 char *BX_strsearch (register char *, char *, char *, int); char *BX_move_to_abs_word (const register char *, char **, int); -char *BX_move_word_rel (const register char *, char **, int); +char *BX_move_word_rel (const char *, char **, int); char *BX_extract (char *, int, int); char *BX_extract2 (const char *, int, int); int BX_wild_match (const char *, const char *); diff --git a/source/words.c b/source/words.c index c63385d..15461d6 100644 --- a/source/words.c +++ b/source/words.c @@ -80,48 +80,54 @@ extern char *BX_move_to_abs_word (const register char *start, char **mark, int w return pointer; } -/* Move a relative number of words from the present mark */ -extern char *BX_move_word_rel (const register char *start, char **mark, int word) +/* move_word_rel() + * + * Take a string and return a pointer offset a number of words relative to a given mark. + * Positive offset N returns a pointer to Nth next word (not counting the current word, + * if the mark is within a word). Negative offset -N returns a pointer to the Nth + * previous word, counting the current word. Offset 0 leaves the mark unchanged. + */ +extern char *BX_move_word_rel (const char *start, char **mark, int word) { - register char *pointer = *mark; - register int counter = word; - char *end = (char *)start + strlen((char *)start); + const char *pointer = *mark; - if (end == start) /* null string, return it */ + if (!*start) /* null string, return it */ return (char *)start; - /* - * XXXX - this is utterly pointless at best, and - * totally wrong at worst. - */ - - if (counter > 0) + if (word >= 0) { - for (;counter > 0 && pointer;counter--) + for (;word > 0 && *pointer;word--) { + /* Move pointer to first space after current word */ while (*pointer && !my_isspace(*pointer)) pointer++; + /* Move pointer to first character of next word */ while (*pointer && my_isspace(*pointer)) pointer++; } } - else if (counter == 0) - pointer = *mark; - else /* counter < 0 */ + else /* word < 0 */ { - for (;counter < 0 && pointer > start;counter++) + /* If we are in between words, find the previous word */ + while (pointer > start && my_isspace(pointer[0])) + pointer--; + /* Move pointer to first character of current word */ + while (pointer > start && !my_isspace(pointer[-1])) + pointer--; + + for (word++; word < 0 && pointer > start; word++) { - while (pointer >= start && my_isspace(*pointer)) + /* Move pointer to first space after previous word. */ + while (pointer > start && my_isspace(pointer[-1])) pointer--; - while (pointer >= start && !my_isspace(*pointer)) + + /* Move pointer to first character of word */ + while (pointer > start && !my_isspace(pointer[-1])) pointer--; } - pointer++; /* bump up to the word we just passed */ } - if (mark) - *mark = pointer; - return pointer; + return *mark = (char *)pointer; } /*