Solve some bug reports

The savannah web site had some new bug report last december.
A lot of them are assemmbly bugs.
See testcase 60 for an overview.
This commit is contained in:
herman ten brugge
2026-01-06 07:49:02 +01:00
parent 9a7edb20d3
commit 8a8388c6ff
13 changed files with 191 additions and 17 deletions

View File

@@ -149,8 +149,11 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }

View File

@@ -257,8 +257,11 @@ void o(uint32_t i)
if (!cur_text_section) if (!cur_text_section)
tcc_error("compiler error! This happens f.ex. if the compiler\n" tcc_error("compiler error! This happens f.ex. if the compiler\n"
"can't evaluate constant expressions outside of a function."); "can't evaluate constant expressions outside of a function.");
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind++] = i&255; cur_text_section->data[ind++] = i&255;
i>>=8; i>>=8;
cur_text_section->data[ind++] = i&255; cur_text_section->data[ind++] = i&255;

View File

@@ -31,8 +31,11 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }

View File

@@ -117,8 +117,11 @@ ST_FUNC void o(unsigned int c)
int ind1 = ind + 4; int ind1 = ind + 4;
if (nocode_wanted) if (nocode_wanted)
return; return;
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
write32le(cur_text_section->data + ind, c); write32le(cur_text_section->data + ind, c);
ind = ind1; ind = ind1;
} }
@@ -274,6 +277,7 @@ static int arm64_type_size(int t)
case VT_DOUBLE: return 3; case VT_DOUBLE: return 3;
case VT_LDOUBLE: return 4; case VT_LDOUBLE: return 4;
case VT_BOOL: return 0; case VT_BOOL: return 0;
case VT_VOID: return 0;
} }
assert(0); assert(0);
return 0; return 0;

View File

@@ -195,8 +195,11 @@ void C67_g(int c)
fprintf(f, " %08X", c); fprintf(f, " %08X", c);
#endif #endif
ind1 = ind + 4; ind1 = ind + 4;
if (ind1 > (int) cur_text_section->data_allocated) if ((unsigned)ind1 > (int) cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c & 0xff; cur_text_section->data[ind] = c & 0xff;
cur_text_section->data[ind + 1] = (c >> 8) & 0xff; cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
cur_text_section->data[ind + 2] = (c >> 16) & 0xff; cur_text_section->data[ind + 2] = (c >> 16) & 0xff;

View File

@@ -126,8 +126,11 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }
@@ -363,7 +366,8 @@ ST_FUNC void load(int r, SValue *sv)
r = 5; r = 5;
} else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
opc = 0xbe0f; /* movsbl */ opc = 0xbe0f; /* movsbl */
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED) ||
(ft & VT_TYPE) == (VT_BOOL | VT_UNSIGNED)) {
opc = 0xb60f; /* movzbl */ opc = 0xb60f; /* movzbl */
} else if ((ft & VT_TYPE) == VT_SHORT) { } else if ((ft & VT_TYPE) == VT_SHORT) {
opc = 0xbf0f; /* movswl */ opc = 0xbf0f; /* movswl */

View File

@@ -98,8 +98,11 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }

View File

@@ -115,8 +115,11 @@ ST_FUNC void o(unsigned int c)
int ind1 = ind + 4; int ind1 = ind + 4;
if (nocode_wanted) if (nocode_wanted)
return; return;
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
write32le(cur_text_section->data + ind, c); write32le(cur_text_section->data + ind, c);
ind = ind1; ind = ind1;
} }

View File

@@ -398,6 +398,8 @@ ST_FUNC int asm_int_expr(TCCState *s1)
asm_expr(s1, &e); asm_expr(s1, &e);
if (e.sym) if (e.sym)
expect("constant"); expect("constant");
if ((int)e.v != e.v)
tcc_error("integer out of range %lld", (long long)e.v);
return e.v; return e.v;
} }
@@ -515,7 +517,7 @@ static void asm_parse_directive(TCCState *s1, int global)
tok1 = TOK_ASMDIR_align; tok1 = TOK_ASMDIR_align;
} }
if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) { if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) {
if (n < 0 || (n & (n-1)) != 0) if (n <= 0 || (n & (n-1)) != 0)
tcc_error("alignment must be a positive power of two"); tcc_error("alignment must be a positive power of two");
offset = (ind + n - 1) & -n; offset = (ind + n - 1) & -n;
size = offset - ind; size = offset - ind;
@@ -677,17 +679,21 @@ static void asm_parse_directive(TCCState *s1, int global)
} }
case TOK_ASMDIR_org: case TOK_ASMDIR_org:
{ {
unsigned long n;
ExprValue e; ExprValue e;
ElfSym *esym; ElfSym *esym;
next(); next();
asm_expr(s1, &e); asm_expr(s1, &e);
n = e.v; n = e.v;
if (n != e.v || n < 0)
range:
tcc_error(".org out of range");
esym = elfsym(e.sym); esym = elfsym(e.sym);
if (esym) { if (esym) {
if (esym->st_shndx != cur_text_section->sh_num) if (esym->st_shndx != cur_text_section->sh_num)
expect("constant or same-section symbol"); expect("constant or same-section symbol");
n += esym->st_value; n += esym->st_value;
if (n < esym->st_value)
goto range;
} }
if (n < ind) if (n < ind)
tcc_error("attempt to .org backwards"); tcc_error("attempt to .org backwards");
@@ -713,6 +719,8 @@ static void asm_parse_directive(TCCState *s1, int global)
do { do {
Sym *sym; Sym *sym;
next(); next();
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM)
tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL));
sym = get_asm_sym(tok, NULL); sym = get_asm_sym(tok, NULL);
if (tok1 != TOK_ASMDIR_hidden) if (tok1 != TOK_ASMDIR_hidden)
sym->type.t &= ~VT_STATIC; sym->type.t &= ~VT_STATIC;
@@ -799,7 +807,7 @@ static void asm_parse_directive(TCCState *s1, int global)
if (tok == TOK_STR) if (tok == TOK_STR)
pstrcat(ident, sizeof(ident), tokc.str.data); pstrcat(ident, sizeof(ident), tokc.str.data);
else else
pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL)); pstrcat(ident, sizeof(ident), get_tok_str(tok, &tokc));
tcc_warning_c(warn_unsupported)("ignoring .ident %s", ident); tcc_warning_c(warn_unsupported)("ignoring .ident %s", ident);
next(); next();
} }
@@ -808,10 +816,11 @@ static void asm_parse_directive(TCCState *s1, int global)
{ {
Sym *sym; Sym *sym;
tok1 = tok;
next(); next();
sym = asm_label_find(tok); sym = asm_label_find(tok);
if (!sym) { if (!sym) {
tcc_error("label not found: %s", get_tok_str(tok, NULL)); tcc_error("label not found: %s", get_tok_str(tok1, NULL));
} }
/* XXX .size name,label2-label1 */ /* XXX .size name,label2-label1 */
tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL)); tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
@@ -828,7 +837,10 @@ static void asm_parse_directive(TCCState *s1, int global)
const char *newtype; const char *newtype;
int st_type; int st_type;
tok1 = tok;
next(); next();
if (tok < TOK_IDENT || tok >= SYM_FIRST_ANOM)
tcc_error("Illegal symbol %s", get_tok_str(tok1, NULL));
sym = get_asm_sym(tok, NULL); sym = get_asm_sym(tok, NULL);
next(); next();
skip(','); skip(',');
@@ -1177,11 +1189,14 @@ static void subst_asm_operands(ASMOperand *operands, int nb_operands,
modifier = *str++; modifier = *str++;
index = find_constraint(operands, nb_operands, str, &str); index = find_constraint(operands, nb_operands, str, &str);
if (index < 0) if (index < 0)
error:
tcc_error("invalid operand reference after %%"); tcc_error("invalid operand reference after %%");
op = &operands[index]; op = &operands[index];
if (modifier == 'l') { if (modifier == 'l') {
cstr_cat(out_str, get_tok_str(op->is_label, NULL), -1); cstr_cat(out_str, get_tok_str(op->is_label, NULL), -1);
} else { } else {
if (op->vt == NULL)
goto error;
sv = *op->vt; sv = *op->vt;
if (op->reg >= 0) { if (op->reg >= 0) {
sv.r = op->reg; sv.r = op->reg;
@@ -1318,6 +1333,8 @@ ST_FUNC void asm_instr(void)
tcc_error("too many asm operands"); tcc_error("too many asm operands");
if (tok < TOK_UIDENT) if (tok < TOK_UIDENT)
expect("label identifier"); expect("label identifier");
memset(operands + nb_operands + nb_labels, 0,
sizeof(operands[0]));
operands[nb_operands + nb_labels++].id = tok; operands[nb_operands + nb_labels++].id = tok;
csym = label_find(tok); csym = label_find(tok);

View File

@@ -7837,6 +7837,9 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
ElfW_Rel *rel; ElfW_Rel *rel;
esym = elfsym(vtop->sym); esym = elfsym(vtop->sym);
ssec = tcc_state->sections[esym->st_shndx]; ssec = tcc_state->sections[esym->st_shndx];
if (esym->st_value + (int)vtop->c.i + size > ssec->data_offset)
section_add(ssec, esym->st_value + (int)vtop->c.i +
size - ssec->data_offset, 1);
memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size); memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size);
if (ssec->reloc) { if (ssec->reloc) {
/* We need to copy over all memory contents, and that /* We need to copy over all memory contents, and that

View File

@@ -551,4 +551,84 @@ int main(int argc, char **argv)
} }
#elif defined test_jmp_label
int main(void) {
asm goto("jmp %[label]" : : : : label);
}
#elif defined test_void_ternary
int main() {
unsigned long b = 0;
if ((b ? (void)0 : (long long)b))
}
#elif defined test_init_int_string
int fsB = "";
//#elif defined test_constant1
// results differs on 32/64 bits targets
// reports 64: constant expression expected
// reports 32: constant exceeds 32 bit
//e[1.0 < r()
//
//#elif defined test_constant2
// results differs on 32/64 bits targets
// reports 64: constant expression expected
// reports 32: constant exceeds 32 bit
//e[1 < r()-1.
#elif defined test_asm1
asm (".align 8589934592");
#elif defined test_asm2
asm (".balign 8589934592");
#elif defined test_asm3
asm (".global ");
#elif defined test_asm4
asm (".type (a,cr0,digit)");
#elif defined test_asm5
asm (".type $6");
#elif defined test_asm6
asm (".global $-3");
#elif defined test_asm7
asm (".global (dx,0X2D,digit)");
#elif defined test_asm8
asm (".size 0XA");
#elif defined test_asm9
asm (".weak (fs:0)");
#elif defined test_asm10
asm (".align 0");
#elif defined test_asm11
asm (".org 33824993159184");
//#elif defined test_big
// results differs on 32/64 bits targets
// reports 64: error: program too big
// reports 32: memory full
//asm (".org 0x7fffffff");
//asm (".byte 1, 2, 3, 4");
#endif #endif

View File

@@ -262,3 +262,45 @@ bar 15 12 34
[test_scope_3] [test_scope_3]
60_errors_and_warnings.c:548: warning: assignment from incompatible pointer type 60_errors_and_warnings.c:548: warning: assignment from incompatible pointer type
60_errors_and_warnings.c:549: error: initialization of incomplete type 60_errors_and_warnings.c:549: error: initialization of incomplete type
[test_jmp_label]
60_errors_and_warnings.c:557: error: invalid operand reference after %
[test_void_ternary]
60_errors_and_warnings.c:564: error: invalid operand types for binary operation
[test_init_int_string]
60_errors_and_warnings.c:569: warning: assignment makes integer from pointer without a cast
[test_asm1]
60_errors_and_warnings.c:584: error: integer out of range 8589934592
[test_asm2]
60_errors_and_warnings.c:588: error: integer out of range 8589934592
[test_asm3]
60_errors_and_warnings.c:592: error: Illegal symbol .global
[test_asm4]
60_errors_and_warnings.c:597: error: Illegal symbol .type
[test_asm5]
60_errors_and_warnings.c:601: error: Illegal symbol .type
[test_asm6]
60_errors_and_warnings.c:605: error: Illegal symbol .global
[test_asm7]
60_errors_and_warnings.c:609: error: Illegal symbol .global
[test_asm8]
60_errors_and_warnings.c:613: error: label not found: .size
[test_asm9]
60_errors_and_warnings.c:617: error: Illegal symbol .weak
[test_asm10]
60_errors_and_warnings.c:620: error: alignment must be a positive power of two
[test_asm11]
60_errors_and_warnings.c:624: error: .org out of range

View File

@@ -175,8 +175,11 @@ ST_FUNC void g(int c)
if (nocode_wanted) if (nocode_wanted)
return; return;
ind1 = ind + 1; ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated) if ((unsigned)ind1 > cur_text_section->data_allocated) {
if (ind1 < 0)
tcc_error("program too big");
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
}
cur_text_section->data[ind] = c; cur_text_section->data[ind] = c;
ind = ind1; ind = ind1;
} }
@@ -444,7 +447,8 @@ void load(int r, SValue *sv)
b = 0xdb, r = 5; /* fldt */ b = 0xdb, r = 5; /* fldt */
} else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
b = 0xbe0f; /* movsbl */ b = 0xbe0f; /* movsbl */
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED) ||
(ft & VT_TYPE) == (VT_BOOL | VT_UNSIGNED)) {
b = 0xb60f; /* movzbl */ b = 0xb60f; /* movzbl */
} else if ((ft & VT_TYPE) == VT_SHORT) { } else if ((ft & VT_TYPE) == VT_SHORT) {
b = 0xbf0f; /* movswl */ b = 0xbf0f; /* movswl */
@@ -538,6 +542,7 @@ void load(int r, SValue *sv)
o(0x44 + REG_VALUE(r)*8); /* %xmmN */ o(0x44 + REG_VALUE(r)*8); /* %xmmN */
o(0xf024); o(0xf024);
} else { } else {
if (!nocode_wanted)
assert((v >= TREG_XMM0) && (v <= TREG_XMM7)); assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
if ((ft & VT_BTYPE) == VT_FLOAT) { if ((ft & VT_BTYPE) == VT_FLOAT) {
o(0x100ff3); o(0x100ff3);
@@ -548,6 +553,7 @@ void load(int r, SValue *sv)
o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8); o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8);
} }
} else if (r == TREG_ST0) { } else if (r == TREG_ST0) {
if (!nocode_wanted)
assert((v >= TREG_XMM0) && (v <= TREG_XMM7)); assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
/* gen_cvt_ftof(VT_LDOUBLE); */ /* gen_cvt_ftof(VT_LDOUBLE); */
/* movsd %xmmN,-0x10(%rsp) */ /* movsd %xmmN,-0x10(%rsp) */