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.
This commit is contained in:
Kevin Easton
2017-11-12 22:43:20 +11:00
parent a71ee883e1
commit 5e40c1ac01
2 changed files with 30 additions and 24 deletions

View File

@@ -134,7 +134,7 @@ char * base64_encode (const void *data, size_t size);
#define EOS 32767 #define EOS 32767
char *BX_strsearch (register char *, char *, char *, int); char *BX_strsearch (register char *, char *, char *, int);
char *BX_move_to_abs_word (const register 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_extract (char *, int, int);
char *BX_extract2 (const char *, int, int); char *BX_extract2 (const char *, int, int);
int BX_wild_match (const char *, const char *); int BX_wild_match (const char *, const char *);

View File

@@ -80,48 +80,54 @@ extern char *BX_move_to_abs_word (const register char *start, char **mark, int w
return pointer; return pointer;
} }
/* Move a relative number of words from the present mark */ /* move_word_rel()
extern char *BX_move_word_rel (const register char *start, char **mark, int word) *
* 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; const char *pointer = *mark;
register int counter = word;
char *end = (char *)start + strlen((char *)start);
if (end == start) /* null string, return it */ if (!*start) /* null string, return it */
return (char *)start; return (char *)start;
/* if (word >= 0)
* XXXX - this is utterly pointless at best, and
* totally wrong at worst.
*/
if (counter > 0)
{ {
for (;counter > 0 && pointer;counter--) for (;word > 0 && *pointer;word--)
{ {
/* Move pointer to first space after current word */
while (*pointer && !my_isspace(*pointer)) while (*pointer && !my_isspace(*pointer))
pointer++; pointer++;
/* Move pointer to first character of next word */
while (*pointer && my_isspace(*pointer)) while (*pointer && my_isspace(*pointer))
pointer++; pointer++;
} }
} }
else if (counter == 0) else /* word < 0 */
pointer = *mark;
else /* counter < 0 */
{ {
for (;counter < 0 && pointer > start;counter++) /* If we are in between words, find the previous word */
{ while (pointer > start && my_isspace(pointer[0]))
while (pointer >= start && my_isspace(*pointer))
pointer--; pointer--;
while (pointer >= start && !my_isspace(*pointer)) /* Move pointer to first character of current word */
while (pointer > start && !my_isspace(pointer[-1]))
pointer--;
for (word++; word < 0 && pointer > start; word++)
{
/* Move pointer to first space after previous word. */
while (pointer > start && my_isspace(pointer[-1]))
pointer--;
/* Move pointer to first character of word */
while (pointer > start && !my_isspace(pointer[-1]))
pointer--; pointer--;
} }
pointer++; /* bump up to the word we just passed */
} }
if (mark) return *mark = (char *)pointer;
*mark = pointer;
return pointer;
} }
/* /*