tccpp: alternative fix for #include_next infinite loop bug

This replaces commit 3d409b0889

- 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
master
grischka 2013-01-06 17:20:44 +01:00
parent e92dbe4686
commit 2358b378b3
4 changed files with 41 additions and 80 deletions

View File

@ -34,10 +34,6 @@ ST_DATA struct TCCState *tcc_state;
/********************************************************/ /********************************************************/
#ifndef _WIN32
#include <limits.h>
#endif
#ifdef ONE_SOURCE #ifdef ONE_SOURCE
#include "tccpp.c" #include "tccpp.c"
#include "tccgen.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'); 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); dynarray_add(p_ary, p_nb_ary, str.data);
#endif
in = p+1; in = p+1;
} while (*p); } while (*p);
} }

5
tcc.h
View File

@ -422,9 +422,7 @@ typedef struct BufferedFile {
int ifndef_macro; /* #ifndef macro / #endif search */ int ifndef_macro; /* #ifndef macro / #endif search */
int ifndef_macro_saved; /* saved ifndef_macro */ int ifndef_macro_saved; /* saved ifndef_macro */
int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */ int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
char inc_type; /* type of include */ char filename[1024]; /* filename */
char inc_filename[512]; /* filename specified by the user */
char filename[1024]; /* current filename - here to simplify code */
unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */ unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
} BufferedFile; } BufferedFile;
@ -460,7 +458,6 @@ typedef struct InlineFunc {
typedef struct CachedInclude { typedef struct CachedInclude {
int ifndef_macro; int ifndef_macro;
int hash_next; /* -1 if none */ int hash_next; /* -1 if none */
char type; /* '"' or '>' to give include type */
char filename[1]; /* path specified in #include */ char filename[1]; /* path specified in #include */
} CachedInclude; } CachedInclude;

View File

@ -3284,8 +3284,8 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
{ {
Sym *s; Sym *s;
CType type1, *type2; CType type1, *type2;
int qualifiers, storage, saved_nocode_wanted; int qualifiers, storage;
while (tok == '*') { while (tok == '*') {
qualifiers = 0; qualifiers = 0;
redo: redo:
@ -3339,12 +3339,12 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
storage = type->t & VT_STORAGE; storage = type->t & VT_STORAGE;
type->t &= ~VT_STORAGE; type->t &= ~VT_STORAGE;
if (storage & VT_STATIC) { if (storage & VT_STATIC) {
saved_nocode_wanted = nocode_wanted; int saved_nocode_wanted = nocode_wanted;
nocode_wanted = 1; nocode_wanted = 1;
} post_type(type, ad);
post_type(type, ad);
if (storage & VT_STATIC)
nocode_wanted = saved_nocode_wanted; nocode_wanted = saved_nocode_wanted;
} else
post_type(type, ad);
type->t |= storage; type->t |= storage;
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
parse_attribute(ad); parse_attribute(ad);

77
tccpp.c
View File

@ -1242,13 +1242,12 @@ ST_FUNC void parse_define(void)
define_push(v, t, str.str, first); 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; const unsigned char *s;
unsigned int h; unsigned int h;
h = TOK_HASH_INIT; h = TOK_HASH_INIT;
h = TOK_HASH_FUNC(h, type);
s = filename; s = filename;
while (*s) { while (*s) {
h = TOK_HASH_FUNC(h, *s); h = TOK_HASH_FUNC(h, *s);
@ -1258,45 +1257,39 @@ static inline int hash_cached_include(int type, const char *filename)
return h; return h;
} }
/* XXX: use a token or a hash table to accelerate matching ? */ static CachedInclude *search_cached_include(TCCState *s1, const char *filename)
static CachedInclude *search_cached_include(TCCState *s1,
int type, const char *filename)
{ {
CachedInclude *e; CachedInclude *e;
int i, h; int i, h;
h = hash_cached_include(type, filename); h = hash_cached_include(filename);
i = s1->cached_includes_hash[h]; i = s1->cached_includes_hash[h];
for(;;) { for(;;) {
if (i == 0) if (i == 0)
break; break;
e = s1->cached_includes[i - 1]; e = s1->cached_includes[i - 1];
if (e->type == type && !PATHCMP(e->filename, filename)) if (0 == PATHCMP(e->filename, filename))
return e; return e;
i = e->hash_next; i = e->hash_next;
} }
return NULL; return NULL;
} }
static inline void add_cached_include(TCCState *s1, int type, static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro)
const char *filename, int ifndef_macro)
{ {
CachedInclude *e; CachedInclude *e;
int h; int h;
if (search_cached_include(s1, type, filename)) if (search_cached_include(s1, filename))
return; return;
#ifdef INC_DEBUG #ifdef INC_DEBUG
printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL)); printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
#endif #endif
e = tcc_malloc(sizeof(CachedInclude) + strlen(filename)); e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
if (!e)
return;
e->type = type;
strcpy(e->filename, filename); strcpy(e->filename, filename);
e->ifndef_macro = ifndef_macro; e->ifndef_macro = ifndef_macro;
dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e); dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
/* add in hash table */ /* add in hash table */
h = hash_cached_include(type, filename); h = hash_cached_include(filename);
e->hash_next = s1->cached_includes_hash[h]; e->hash_next = s1->cached_includes_hash[h];
s1->cached_includes_hash[h] = s1->nb_cached_includes; 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) if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
tcc_error("#include recursion too deep"); 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; n = s1->nb_include_paths + s1->nb_sysinclude_paths;
for (i = -2; i < n; ++i) { for (i = -2; i < n; ++i) {
char buf1[sizeof file->filename]; char buf1[sizeof file->filename];
CachedInclude *e; CachedInclude *e;
BufferedFile **f;
const char *path; const char *path;
int size, fd;
if (i == -2) { if (i == -2) {
/* check absolute include path */ /* check absolute include path */
if (!IS_ABSPATH(buf)) if (!IS_ABSPATH(buf))
continue; continue;
buf1[0] = 0; buf1[0] = 0;
i = n; /* force end loop */
} else if (i == -1) { } else if (i == -1) {
/* search in current dir if "header.h" */ /* search in current dir if "header.h" */
if (c != '\"') if (c != '\"')
continue; continue;
size = tcc_basename(file->filename) - file->filename; path = file->filename;
memcpy(buf1, file->filename, size); pstrncpy(buf1, path, tcc_basename(path) - path);
buf1[size] = '\0';
} else { } else {
/* search in all the include paths */ /* search in all the include paths */
@ -1470,41 +1465,37 @@ ST_FUNC void preprocess(int is_bof)
pstrcat(buf1, sizeof(buf1), buf); 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)) { if (e && define_find(e->ifndef_macro)) {
/* no need to parse the include because the 'ifndef macro' /* no need to parse the include because the 'ifndef macro'
is defined */ is defined */
#ifdef INC_DEBUG #ifdef INC_DEBUG
printf("%s: skipping %s\n", file->filename, buf); printf("%s: skipping cached %s\n", file->filename, buf1);
#endif #endif
fd = 0;
} else {
fd = tcc_open(s1, buf1);
if (fd < 0)
continue;
}
if (tok == TOK_INCLUDE_NEXT) {
tok = TOK_INCLUDE;
if (fd)
tcc_close();
continue;
}
if (0 == fd)
goto include_done; goto include_done;
}
if (tcc_open(s1, buf1) < 0)
include_trynext:
continue;
#ifdef INC_DEBUG #ifdef INC_DEBUG
printf("%s: including %s\n", file->filename, buf1); printf("%s: including %s\n", file->prev->filename, file->filename);
#endif #endif
/* update target deps */ /* update target deps */
dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps, dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
tcc_strdup(buf1)); tcc_strdup(buf1));
/* XXX: fix current line init */ /* push current file in stack */
/* push current file in stack */ ++s1->include_stack_ptr;
*s1->include_stack_ptr++ = file->prev;
file->inc_type = c;
pstrcpy(file->inc_filename, sizeof(file->inc_filename), buf1);
/* add include file debug info */ /* add include file debug info */
if (s1->do_debug) if (s1->do_debug)
put_stabs(file->filename, N_BINCL, 0, 0, 0); put_stabs(file->filename, N_BINCL, 0, 0, 0);
@ -2137,8 +2128,8 @@ static inline void next_nomacro1(void)
#ifdef INC_DEBUG #ifdef INC_DEBUG
printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL)); printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
#endif #endif
add_cached_include(s1, file->inc_type, file->inc_filename, add_cached_include(s1, file->filename, file->ifndef_macro_saved);
file->ifndef_macro_saved); tok_flags &= ~TOK_FLAG_ENDIF;
} }
/* add end of include file debug info */ /* add end of include file debug info */