diff options
author | Michael Stahl <mstahl@redhat.com> | 2012-08-08 23:30:40 +0200 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2012-08-08 23:36:37 +0200 |
commit | 3ea6b1c1594fa3fdb7e13c544b3beecd369b67d0 (patch) | |
tree | 56df58adfa169e9403a6d70d6c3ea9d0dd832ea9 /solenv | |
parent | 45a3e4dd7941e3cf5c1be5e966872338c3be1110 (diff) |
concat-deps: fix crashes due to modifying hash keys:
After a string has been passed as key parameter to hash_store, it must
not be modified, as happens in the print_nodotdot and print_fullpaths
functions; if it doesn't crash then the dep files are twice as large
in a MSVC build because duplicates are not eliminated.
(regression from c2b467b84a81bd45ca9df1f7f07e2700fd6e396a)
Change-Id: I0ae96a7fbcefa20b118717d923f60b4f2255a642
Diffstat (limited to 'solenv')
-rw-r--r-- | solenv/bin/concat-deps.c | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/solenv/bin/concat-deps.c b/solenv/bin/concat-deps.c index 4c2aaf44adbc..38d251f2b592 100644 --- a/solenv/bin/concat-deps.c +++ b/solenv/bin/concat-deps.c @@ -687,52 +687,58 @@ int fd; return buffer; } -static inline void print_nodotdot(char* path) +static void _cancel_relative(char* base, char** ref_cursor, char** ref_cursor_out, char* end) { -char* pathpart; -char* lastnondotdot; - pathpart = path; - lastnondotdot = NULL; - while(pathpart != NULL) + char* cursor = *ref_cursor; + char* cursor_out = *ref_cursor_out; + + do { - if(strncmp(pathpart, "/../", 4) == 0) - { - if(!lastnondotdot) - break; /* this should never happen with abs. paths */ - memmove(lastnondotdot, pathpart+4, strlen(pathpart)-3); - lastnondotdot = NULL; - pathpart = path; - } - else - { - lastnondotdot = pathpart+1; - pathpart = strchr(pathpart+1,'/'); - } + cursor += 3; + while(cursor_out > base && cursor_out[-1] == '/') + cursor_out--; + while(cursor_out > base && *--cursor_out != '/'); + } + while(cursor + 3 < end && !memcmp(cursor, "/../", 4)); + *ref_cursor = cursor; + *ref_cursor_out = cursor_out; +} + +static inline void eat_space(char ** token) +{ + while ((' ' == **token) || ('\t' == **token)) { + ++(*token); } - fputs(path, stdout); } /* prefix paths to absolute */ static inline void print_fullpaths(char* line) { char* token; +char* end; - token = strtok(line," "); - while(token != NULL) + token = line; + eat_space(&token); + while (*token) { + end = token; + while (*end && (' ' != *end) && ('\t' != *end)) { + ++end; + } if(*token == ':' || *token == '\\' || *token == '/' || *token == '$' || ':' == token[1]) { - fputs(token, stdout); + fwrite(token, end - token, 1, stdout); } else { fputs(base_dir_var, stdout); fputc('/', stdout); - print_nodotdot(token); + fwrite(token, end - token, 1, stdout); } fputc(' ', stdout); - token = strtok(NULL," "); + token = end; + eat_space(&token); } } @@ -767,6 +773,13 @@ off_t size; } else if(*cursor == '/') { + if(cursor + 3 < end) + { + if(!memcmp(cursor, "/../", 4)) + { + _cancel_relative(base, &cursor, &cursor_out, end); + } + } *cursor_out++ = *cursor++; } else if(*cursor == '\n') @@ -785,6 +798,8 @@ off_t size; */ if(hash_store(dep_hash, base, (int)(cursor_out - base))) { + /* DO NOT modify base after it has been added + as key by hash_store */ print_fullpaths(base); putc('\n', stdout); } |