From 2358b378b3cd526956713f033f5a0ecaa5f63951 Mon Sep 17 00:00:00 2001 From: grischka Date: Sun, 6 Jan 2013 17:20:44 +0100 Subject: [PATCH] tccpp: alternative fix for #include_next infinite loop bug This replaces commit 3d409b08893873b917ccb8c34398bc41a4e84d7c - revert old fix in libtcc.c - #include_next: look up the file in the include stack to see if it is already included. Also: - streamline include code - remove 'type' from struct CachedInclude (obsolete because we check full filename anyway) - remove inc_type & inc_filename from struct Bufferedfile (obsolete) - fix bug with TOK_FLAG_ENDIF not being reset - unrelated: get rid of an 'variable potentially uninitialized' warning --- libtcc.c | 27 ------------------------ tcc.h | 5 +---- tccgen.c | 12 +++++------ tccpp.c | 73 ++++++++++++++++++++++++++++------------------------------------ 4 files changed, 39 insertions(+), 78 deletions(-) diff --git a/libtcc.c b/libtcc.c index 6c04caa0..b0a9b1a4 100644 --- a/libtcc.c +++ b/libtcc.c @@ -34,10 +34,6 @@ ST_DATA struct TCCState *tcc_state; /********************************************************/ -#ifndef _WIN32 -#include -#endif - #ifdef ONE_SOURCE #include "tccpp.c" #include "tccgen.c" @@ -322,30 +318,7 @@ static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char } } cstr_ccat(&str, '\0'); -#ifndef _WIN32 - { - int i, do_include; - char tmp[PATH_MAX]; - - if (realpath(str.data, tmp)) { - str.size = 0; - cstr_cat(&str, tmp); - cstr_ccat(&str, '\0'); - } - - do_include = 1; - for (i = 0; i < *p_nb_ary && do_include; i++) { - do_include = do_include && - strcmp((char*)str.data, (char*)(*p_ary)[i]); - } - - if (do_include) { - dynarray_add(p_ary, p_nb_ary, str.data); - } - } -#else dynarray_add(p_ary, p_nb_ary, str.data); -#endif in = p+1; } while (*p); } diff --git a/tcc.h b/tcc.h index 8e794301..5489b497 100644 --- a/tcc.h +++ b/tcc.h @@ -422,9 +422,7 @@ typedef struct BufferedFile { int ifndef_macro; /* #ifndef macro / #endif search */ int ifndef_macro_saved; /* saved ifndef_macro */ int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ - char inc_type; /* type of include */ - char inc_filename[512]; /* filename specified by the user */ - char filename[1024]; /* current filename - here to simplify code */ + char filename[1024]; /* filename */ unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */ } BufferedFile; @@ -460,7 +458,6 @@ typedef struct InlineFunc { typedef struct CachedInclude { int ifndef_macro; int hash_next; /* -1 if none */ - char type; /* '"' or '>' to give include type */ char filename[1]; /* path specified in #include */ } CachedInclude; diff --git a/tccgen.c b/tccgen.c index 5a79f491..71555cd3 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3284,8 +3284,8 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) { Sym *s; CType type1, *type2; - int qualifiers, storage, saved_nocode_wanted; - + int qualifiers, storage; + while (tok == '*') { qualifiers = 0; redo: @@ -3339,12 +3339,12 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td) storage = type->t & VT_STORAGE; type->t &= ~VT_STORAGE; if (storage & VT_STATIC) { - saved_nocode_wanted = nocode_wanted; + int saved_nocode_wanted = nocode_wanted; nocode_wanted = 1; - } - post_type(type, ad); - if (storage & VT_STATIC) + post_type(type, ad); nocode_wanted = saved_nocode_wanted; + } else + post_type(type, ad); type->t |= storage; if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(ad); diff --git a/tccpp.c b/tccpp.c index 4b7b4fa8..05098e18 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1242,13 +1242,12 @@ ST_FUNC void parse_define(void) define_push(v, t, str.str, first); } -static inline int hash_cached_include(int type, const char *filename) +static inline int hash_cached_include(const char *filename) { const unsigned char *s; unsigned int h; h = TOK_HASH_INIT; - h = TOK_HASH_FUNC(h, type); s = filename; while (*s) { h = TOK_HASH_FUNC(h, *s); @@ -1258,45 +1257,39 @@ static inline int hash_cached_include(int type, const char *filename) return h; } -/* XXX: use a token or a hash table to accelerate matching ? */ -static CachedInclude *search_cached_include(TCCState *s1, - int type, const char *filename) +static CachedInclude *search_cached_include(TCCState *s1, const char *filename) { CachedInclude *e; int i, h; - h = hash_cached_include(type, filename); + h = hash_cached_include(filename); i = s1->cached_includes_hash[h]; for(;;) { if (i == 0) break; e = s1->cached_includes[i - 1]; - if (e->type == type && !PATHCMP(e->filename, filename)) + if (0 == PATHCMP(e->filename, filename)) return e; i = e->hash_next; } return NULL; } -static inline void add_cached_include(TCCState *s1, int type, - const char *filename, int ifndef_macro) +static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro) { CachedInclude *e; int h; - if (search_cached_include(s1, type, filename)) + if (search_cached_include(s1, filename)) return; #ifdef INC_DEBUG printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL)); #endif e = tcc_malloc(sizeof(CachedInclude) + strlen(filename)); - if (!e) - return; - e->type = type; strcpy(e->filename, filename); e->ifndef_macro = ifndef_macro; dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e); /* add in hash table */ - h = hash_cached_include(type, filename); + h = hash_cached_include(filename); e->hash_next = s1->cached_includes_hash[h]; s1->cached_includes_hash[h] = s1->nb_cached_includes; } @@ -1436,27 +1429,29 @@ ST_FUNC void preprocess(int is_bof) if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE) tcc_error("#include recursion too deep"); + /* store current file in stack, but increment stack later below */ + *s1->include_stack_ptr = file; n = s1->nb_include_paths + s1->nb_sysinclude_paths; for (i = -2; i < n; ++i) { char buf1[sizeof file->filename]; CachedInclude *e; + BufferedFile **f; const char *path; - int size, fd; if (i == -2) { /* check absolute include path */ if (!IS_ABSPATH(buf)) continue; buf1[0] = 0; + i = n; /* force end loop */ } else if (i == -1) { /* search in current dir if "header.h" */ if (c != '\"') continue; - size = tcc_basename(file->filename) - file->filename; - memcpy(buf1, file->filename, size); - buf1[size] = '\0'; + path = file->filename; + pstrncpy(buf1, path, tcc_basename(path) - path); } else { /* search in all the include paths */ @@ -1470,41 +1465,37 @@ ST_FUNC void preprocess(int is_bof) pstrcat(buf1, sizeof(buf1), buf); - e = search_cached_include(s1, c, buf1); + if (tok == TOK_INCLUDE_NEXT) + for (f = s1->include_stack_ptr; f >= s1->include_stack; --f) + if (0 == PATHCMP((*f)->filename, buf1)) { +#ifdef INC_DEBUG + printf("%s: #include_next skipping %s\n", file->filename, buf1); +#endif + goto include_trynext; + } + + e = search_cached_include(s1, buf1); if (e && define_find(e->ifndef_macro)) { /* no need to parse the include because the 'ifndef macro' is defined */ #ifdef INC_DEBUG - printf("%s: skipping %s\n", file->filename, buf); + printf("%s: skipping cached %s\n", file->filename, buf1); #endif - fd = 0; - } else { - fd = tcc_open(s1, buf1); - if (fd < 0) - continue; + goto include_done; } - if (tok == TOK_INCLUDE_NEXT) { - tok = TOK_INCLUDE; - if (fd) - tcc_close(); + if (tcc_open(s1, buf1) < 0) +include_trynext: continue; - } - - if (0 == fd) - goto include_done; #ifdef INC_DEBUG - printf("%s: including %s\n", file->filename, buf1); + printf("%s: including %s\n", file->prev->filename, file->filename); #endif /* update target deps */ dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, tcc_strdup(buf1)); - /* XXX: fix current line init */ - /* push current file in stack */ - *s1->include_stack_ptr++ = file->prev; - file->inc_type = c; - pstrcpy(file->inc_filename, sizeof(file->inc_filename), buf1); + /* push current file in stack */ + ++s1->include_stack_ptr; /* add include file debug info */ if (s1->do_debug) put_stabs(file->filename, N_BINCL, 0, 0, 0); @@ -2137,8 +2128,8 @@ static inline void next_nomacro1(void) #ifdef INC_DEBUG printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL)); #endif - add_cached_include(s1, file->inc_type, file->inc_filename, - file->ifndef_macro_saved); + add_cached_include(s1, file->filename, file->ifndef_macro_saved); + tok_flags &= ~TOK_FLAG_ENDIF; } /* add end of include file debug info */ -- 2.11.4.GIT