mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-26 12:04:59 +08:00
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
This commit is contained in:
parent
e92dbe4686
commit
2358b378b3
27
libtcc.c
27
libtcc.c
@ -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
5
tcc.h
@ -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;
|
||||||
|
|
||||||
|
12
tccgen.c
12
tccgen.c
@ -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
77
tccpp.c
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user