Package: publib-dev
Version: 0.38-2    (stable).

Consider the following program:
#include <publib.h>
#include <stdio.h>
int
main(int argc, char** argv)
{
  char* words[100];
  int   wc;
  int   i;

  wc = strsplit(argv[1], words, 100, "=");
  printf("Got %d words\n", wc);
  for(i =0; i < wc; i++) {
    printf("Word %d = '%s'\n", i, words[i]);
  }
}


compiled:

gcc -o demo demo.c -lpub

When invoked:

demo split=this and some more stuff

wc is very large and the words array will include the entire argv
and env and more rather than just:
wc[0] = "split"
wc[1] = "this"

This results from an incorrect loop termination condition in strsplit; The body of that loop looks like:

        while ((start = find_nonsep(end, sep)) != NULL) {
                end = find_sep(start, sep);
                if (count == maxw-1 && find_nonsep(end, sep) != NULL) {
                        words[count] = start;
                        
                }
                if (count < maxw) {
                        *end++ = '\0';
                        words[count] = start;
                }
                ++count;
        }


If count < maxw,  after finding a non separator, and then a separator,
end will point to the byte after the end of the string and the while loop will cycle again, searching for non separators in the data following the input string. This results in both additional words and potentially segfaults depending on the data following the input string and where it lies in memory.

One way to fix this is to terminate the while loop when end >= strlen(s) + s:

e.g.:

int strsplit(char *s, char **words, int maxw, const char *sep) {
        char *start, *end;
        int count;
        size_t size;

        assert(s != NULL);
        assert(words != NULL || maxw == 0);
        assert(sep != NULL);
        assert(!memoverlap(s, strlen(s)+1, sep, strlen(sep)+1));

        count = 0;
        end = s;
        size = strlen(s);
        while (((end - s) <= size) &&
               ((start = find_nonsep(end, sep)) != NULL)) {
                end = find_sep(start, sep);
                if (count == maxw-1 && find_nonsep(end, sep) != NULL) {
                        words[count] = start;

                }
                if (count < maxw) {
                        *end++ = '\0';
                        words[count] = start;
                }
                ++count;
        }

        return count;
}

or, if you prefer a diff:

20a21
>       size_t size;
29c30,31
<       while ((start = find_nonsep(end, sep)) != NULL) {
---
>       size = strlen(s);
> while (((end - s) <= size) && ((start = find_nonsep(end, sep)) != NULL)) {


Ron Fox
NSCL
Michigan State University
East Lansing, MI 48824-1321

Most people get a fair amount of fun out of their lives, but on balance life is suffering, and only the very young or very foolish imagine otherwise. - George Orwell





--
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to