mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-04-12 18:40:23 +08:00
Make any execution limit configurable, add eval limit
Make any "deadman"-style execution limit configurable on the command line (--limit-foo) or via a pragma (%pragma limit foo). Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
d49e6dc08e
commit
987dc9c9db
@ -93,6 +93,7 @@ gprefix
|
||||
gsuffix
|
||||
lprefix
|
||||
lsuffix
|
||||
limit
|
||||
|
||||
; --- Pragma operations
|
||||
subsections_via_symbols ; macho
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 1996-2017 The NASM Authors - All Rights Reserved
|
||||
* Copyright 1996-2018 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
*
|
||||
@ -68,6 +68,7 @@ const struct warning warnings[ERR_WARN_ALL+1] = {
|
||||
{"unknown-pragma", "unknown %pragma facility or directive", false},
|
||||
{"not-my-pragma", "%pragma not applicable to this compilation", false},
|
||||
{"unknown-warning", "unknown warning in -W/-w or warning directive", false},
|
||||
{"negative-rep", "regative %rep count", true},
|
||||
|
||||
/* THIS ENTRY MUST COME LAST */
|
||||
{"all", "all possible warnings", false}
|
||||
|
10
asm/eval.c
10
asm/eval.c
@ -1,6 +1,6 @@
|
||||
/* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* Copyright 1996-2017 The NASM Authors - All Rights Reserved
|
||||
* Copyright 1996-2018 The NASM Authors - All Rights Reserved
|
||||
* See the file AUTHORS included with the NASM distribution for
|
||||
* the specific copyright holders.
|
||||
*
|
||||
@ -72,6 +72,7 @@ static void *scpriv;
|
||||
static int *opflags;
|
||||
|
||||
static struct eval_hints *hint;
|
||||
static int deadman;
|
||||
|
||||
|
||||
/*
|
||||
@ -769,6 +770,11 @@ static expr *expr6(int critical)
|
||||
bool rn_warn;
|
||||
const char *scope;
|
||||
|
||||
if (++deadman > nasm_limit[LIMIT_EVAL]) {
|
||||
nasm_error(ERR_NONFATAL, "expression too long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (i) {
|
||||
case '-':
|
||||
i = scan(scpriv, tokval);
|
||||
@ -954,6 +960,8 @@ expr *evaluate(scanner sc, void *scprivate, struct tokenval *tv,
|
||||
expr *e;
|
||||
expr *f = NULL;
|
||||
|
||||
deadman = 0;
|
||||
|
||||
hint = hints;
|
||||
if (hint)
|
||||
hint->type = EAH_NOHINT;
|
||||
|
284
asm/nasm.c
284
asm/nasm.c
@ -82,6 +82,7 @@ static void nasm_verror_gnu(int severity, const char *fmt, va_list args);
|
||||
static void nasm_verror_vc(int severity, const char *fmt, va_list args);
|
||||
static void nasm_verror_common(int severity, const char *fmt, va_list args);
|
||||
static void usage(void);
|
||||
static void help(char xopt);
|
||||
|
||||
static bool using_debug_info, opt_verbose_info;
|
||||
static const char *debug_format;
|
||||
@ -153,6 +154,60 @@ static char *quote_for_pmake(const char *str);
|
||||
static char *quote_for_wmake(const char *str);
|
||||
static char *(*quote_for_make)(const char *) = quote_for_pmake;
|
||||
|
||||
/*
|
||||
* Execution limits that can be set via a command-line option or %pragma
|
||||
*/
|
||||
|
||||
#define LIMIT_MAX_VAL (INT_MAX >> 1) /* Effectively unlimited */
|
||||
|
||||
int nasm_limit[LIMIT_MAX+1] =
|
||||
{ LIMIT_MAX_VAL, 1000, 1000000, 1000000, 1000000 };
|
||||
|
||||
struct limit_info {
|
||||
const char *name;
|
||||
const char *help;
|
||||
};
|
||||
static const struct limit_info limit_info[LIMIT_MAX+1] = {
|
||||
{ "passes", "total number of passes" },
|
||||
{ "stalled-passes", "number of passes without forward progress" },
|
||||
{ "macro-levels", "levels of macro expansion"},
|
||||
{ "rep", "%rep count" },
|
||||
{ "eval", "expression evaluation descent"}
|
||||
};
|
||||
|
||||
enum directive_result nasm_set_limit(const char *limit, const char *valstr)
|
||||
{
|
||||
int i;
|
||||
int64_t val;
|
||||
bool rn_error;
|
||||
|
||||
for (i = 0; i <= LIMIT_MAX; i++) {
|
||||
if (!nasm_stricmp(limit, limit_info[i].name))
|
||||
break;
|
||||
}
|
||||
if (i > LIMIT_MAX) {
|
||||
nasm_error(ERR_WARNING|ERR_PASS1|ERR_WARN_UNKNOWN_PRAGMA,
|
||||
"unknown limit: `%s'", limit);
|
||||
return DIRR_ERROR;
|
||||
}
|
||||
|
||||
if (!nasm_stricmp(valstr, "unlimited")) {
|
||||
val = LIMIT_MAX_VAL;
|
||||
} else {
|
||||
val = readnum(valstr, &rn_error);
|
||||
if (rn_error || val < 0) {
|
||||
nasm_error(ERR_WARNING|ERR_PASS1|ERR_WARN_BAD_PRAGMA,
|
||||
"invalid limit value: `%s'", limit);
|
||||
return DIRR_ERROR;
|
||||
} else if (val > LIMIT_MAX_VAL) {
|
||||
val = LIMIT_MAX_VAL;
|
||||
}
|
||||
}
|
||||
|
||||
nasm_limit[i] = val;
|
||||
return DIRR_OK;
|
||||
}
|
||||
|
||||
int64_t switch_segment(int32_t segment)
|
||||
{
|
||||
location.segment = segment;
|
||||
@ -717,11 +772,13 @@ static char *quote_for_wmake(const char *str)
|
||||
enum text_options {
|
||||
OPT_BOGUS,
|
||||
OPT_VERSION,
|
||||
OPT_HELP,
|
||||
OPT_ABORT_ON_PANIC,
|
||||
OPT_MANGLE,
|
||||
OPT_INCLUDE,
|
||||
OPT_PRAGMA,
|
||||
OPT_BEFORE
|
||||
OPT_BEFORE,
|
||||
OPT_LIMIT
|
||||
};
|
||||
struct textargs {
|
||||
const char *label;
|
||||
@ -732,6 +789,7 @@ struct textargs {
|
||||
static const struct textargs textopts[] = {
|
||||
{"v", OPT_VERSION, false, 0},
|
||||
{"version", OPT_VERSION, false, 0},
|
||||
{"help", OPT_HELP, false, 0},
|
||||
{"abort-on-panic", OPT_ABORT_ON_PANIC, false, 0},
|
||||
{"prefix", OPT_MANGLE, true, LM_GPREFIX},
|
||||
{"postfix", OPT_MANGLE, true, LM_GSUFFIX},
|
||||
@ -742,6 +800,7 @@ static const struct textargs textopts[] = {
|
||||
{"include", OPT_INCLUDE, true, 0},
|
||||
{"pragma", OPT_PRAGMA, true, 0},
|
||||
{"before", OPT_BEFORE, true, 0},
|
||||
{"limit-", OPT_LIMIT, true, 0},
|
||||
{NULL, OPT_BOGUS, false, 0}
|
||||
};
|
||||
|
||||
@ -756,7 +815,6 @@ static bool stopoptions = false;
|
||||
static bool process_arg(char *p, char *q, int pass)
|
||||
{
|
||||
char *param;
|
||||
int i;
|
||||
bool advance = false;
|
||||
|
||||
if (!p || !p[0])
|
||||
@ -900,71 +958,7 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
printf
|
||||
("usage: nasm [-@ response file] [-o outfile] [-f format] "
|
||||
"[-l listfile]\n"
|
||||
" [options...] [--] filename\n"
|
||||
" or nasm -v (or --v) for version info\n\n"
|
||||
" -t assemble in SciTech TASM compatible mode\n");
|
||||
printf
|
||||
(" -E (or -e) preprocess only (writes output to stdout by default)\n"
|
||||
" -a don't preprocess (assemble only)\n"
|
||||
" -M generate Makefile dependencies on stdout\n"
|
||||
" -MG d:o, missing files assumed generated\n"
|
||||
" -MF file set Makefile dependency file\n"
|
||||
" -MD file assemble and generate dependencies\n"
|
||||
" -MT file dependency target name\n"
|
||||
" -MQ file dependency target name (quoted)\n"
|
||||
" -MP emit phony target\n\n"
|
||||
" -Zfile redirect error messages to file\n"
|
||||
" -s redirect error messages to stdout\n\n"
|
||||
" -g generate debugging information\n\n"
|
||||
" -F format select a debugging format\n\n"
|
||||
" -gformat same as -g -F format\n\n"
|
||||
" -o outfile write output to an outfile\n\n"
|
||||
" -f format select an output format\n\n"
|
||||
" -l listfile write listing to a listfile\n\n"
|
||||
" -Ipath add a pathname to the include file path\n");
|
||||
printf
|
||||
(" -Olevel optimize opcodes, immediates and branch offsets\n"
|
||||
" -O0 no optimization\n"
|
||||
" -O1 minimal optimization\n"
|
||||
" -Ox multipass optimization (default)\n"
|
||||
" -Pfile pre-include a file (also --include)\n"
|
||||
" -Dmacro[=str] pre-define a macro\n"
|
||||
" -Umacro undefine a macro\n"
|
||||
" -Xformat specifiy error reporting format (gnu or vc)\n"
|
||||
" -w+foo enable warning foo (equiv. -Wfoo)\n"
|
||||
" -w-foo disable warning foo (equiv. -Wno-foo)\n"
|
||||
" -w[+-]error[=foo]\n"
|
||||
" promote [specific] warnings to errors\n"
|
||||
" -h show invocation summary and exit\n\n"
|
||||
" --pragma str pre-executes a specific %%pragma\n"
|
||||
" --before str add line (usually a preprocessor statement) before the input\n"
|
||||
" --prefix str prepend the given string to all the given string\n"
|
||||
" to all extern, common and global symbols\n"
|
||||
" --suffix str append the given string to all the given string\n"
|
||||
" to all extern, common and global symbols\n"
|
||||
" --lprefix str prepend the given string to all other symbols\n"
|
||||
"\n"
|
||||
"Response files should contain command line parameters,\n"
|
||||
"one per line.\n"
|
||||
"\n"
|
||||
"Warnings for the -W/-w options:\n");
|
||||
for (i = 0; i <= ERR_WARN_ALL; i++)
|
||||
printf(" %-23s %s%s\n",
|
||||
warnings[i].name, warnings[i].help,
|
||||
i == ERR_WARN_ALL ? "\n" :
|
||||
warnings[i].enabled ? " (default on)" :
|
||||
" (default off)");
|
||||
if (p[2] == 'f') {
|
||||
printf("valid output formats for -f are"
|
||||
" (`*' denotes default):\n");
|
||||
ofmt_list(ofmt, stdout);
|
||||
} else {
|
||||
printf("For a list of valid output formats, use -hf.\n");
|
||||
printf("For a list of debug formats, use -f <form> -y.\n");
|
||||
}
|
||||
help(p[2]);
|
||||
exit(0); /* never need usage message here */
|
||||
break;
|
||||
|
||||
@ -1068,25 +1062,61 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
case '-':
|
||||
{
|
||||
const struct textargs *tx;
|
||||
size_t olen, plen;
|
||||
|
||||
if (p[2] == 0) { /* -- => stop processing options */
|
||||
p += 2;
|
||||
|
||||
if (!*p) { /* -- => stop processing options */
|
||||
stopoptions = true;
|
||||
break;
|
||||
}
|
||||
|
||||
plen = strlen(p);
|
||||
for (tx = textopts; tx->label; tx++) {
|
||||
if (!nasm_stricmp(p + 2, tx->label))
|
||||
break;
|
||||
olen = strlen(tx->label);
|
||||
|
||||
if (olen > plen)
|
||||
continue;
|
||||
|
||||
if (nasm_memicmp(p, tx->label, olen))
|
||||
continue;
|
||||
|
||||
if (tx->label[olen-1] == '-')
|
||||
break; /* Incomplete option */
|
||||
|
||||
if (!p[olen] || p[olen] == '=')
|
||||
break; /* Complete option */
|
||||
}
|
||||
|
||||
if (!tx->label) {
|
||||
nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
|
||||
"unrecognized option `--%s'", p);
|
||||
}
|
||||
|
||||
param = strchr(p+olen, '=');
|
||||
if (param)
|
||||
*param++ = '\0';
|
||||
|
||||
if (tx->need_arg) {
|
||||
if (!q) {
|
||||
if (!param) {
|
||||
param = q;
|
||||
advance = true;
|
||||
}
|
||||
|
||||
/* Note: a null string is a valid parameter */
|
||||
if (!param) {
|
||||
nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
|
||||
"option `--%s' requires an argument",
|
||||
p + 2);
|
||||
p);
|
||||
break;
|
||||
}
|
||||
advance = true;
|
||||
} else {
|
||||
if (param) {
|
||||
nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
|
||||
"option `--%s' does not take an argument",
|
||||
p);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
switch (tx->opt) {
|
||||
@ -1098,7 +1128,7 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
break;
|
||||
case OPT_MANGLE:
|
||||
if (pass == 2)
|
||||
set_label_mangle(tx->pvt, q);
|
||||
set_label_mangle(tx->pvt, param);
|
||||
break;
|
||||
case OPT_INCLUDE:
|
||||
if (pass == 2)
|
||||
@ -1106,16 +1136,19 @@ static bool process_arg(char *p, char *q, int pass)
|
||||
break;
|
||||
case OPT_PRAGMA:
|
||||
if (pass == 2)
|
||||
preproc->pre_command("pragma", q);
|
||||
preproc->pre_command("pragma", param);
|
||||
break;
|
||||
case OPT_BEFORE:
|
||||
if (pass == 2)
|
||||
preproc->pre_command(NULL, q);
|
||||
preproc->pre_command(NULL, param);
|
||||
break;
|
||||
case OPT_BOGUS:
|
||||
nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
|
||||
"unrecognized option `--%s'", p + 2);
|
||||
case OPT_LIMIT:
|
||||
if (pass == 2)
|
||||
nasm_set_limit(p+olen, param);
|
||||
break;
|
||||
case OPT_HELP:
|
||||
help(0);
|
||||
exit(0);
|
||||
default:
|
||||
panic();
|
||||
}
|
||||
@ -1325,9 +1358,8 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
|
||||
char *line;
|
||||
insn output_ins;
|
||||
int i;
|
||||
int pass_max;
|
||||
uint64_t prev_offset_changed;
|
||||
unsigned int stall_count = 0; /* Make sure we make forward progress... */
|
||||
int stall_count = 0; /* Make sure we make forward progress... */
|
||||
|
||||
switch (cmd_sb) {
|
||||
case 16:
|
||||
@ -1348,7 +1380,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
|
||||
/* Any segment numbers allocated before this point are permanent */
|
||||
seg_alloc_setup_done();
|
||||
|
||||
pass_max = prev_offset_changed = (INT_MAX >> 1) + 2; /* Almost unlimited */
|
||||
prev_offset_changed = nasm_limit[LIMIT_PASSES];
|
||||
for (passn = 1; pass0 <= 2; passn++) {
|
||||
pass1 = pass0 == 2 ? 2 : 1; /* 1, 1, 1, ..., 1, 2 */
|
||||
pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */
|
||||
@ -1585,7 +1617,8 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
|
||||
if (terminate_after_phase)
|
||||
break;
|
||||
|
||||
if ((stall_count > 997U) || (passn >= pass_max)) {
|
||||
if ((stall_count > nasm_limit[LIMIT_STALLED]) ||
|
||||
(passn >= nasm_limit[LIMIT_PASSES])) {
|
||||
/* We get here if the labels don't converge
|
||||
* Example: FOO equ FOO + 1
|
||||
*/
|
||||
@ -1844,3 +1877,88 @@ static void usage(void)
|
||||
{
|
||||
fputs("type `nasm -h' for help\n", error_file);
|
||||
}
|
||||
|
||||
static void help(const char xopt)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf
|
||||
("usage: nasm [-@ response file] [-o outfile] [-f format] "
|
||||
"[-l listfile]\n"
|
||||
" [options...] [--] filename\n"
|
||||
" or nasm -v (or --v) for version info\n\n"
|
||||
"\n"
|
||||
"Response files should contain command line parameters,\n"
|
||||
"one per line.\n"
|
||||
"\n"
|
||||
" -t assemble in SciTech TASM compatible mode\n");
|
||||
printf
|
||||
(" -E (or -e) preprocess only (writes output to stdout by default)\n"
|
||||
" -a don't preprocess (assemble only)\n"
|
||||
" -M generate Makefile dependencies on stdout\n"
|
||||
" -MG d:o, missing files assumed generated\n"
|
||||
" -MF file set Makefile dependency file\n"
|
||||
" -MD file assemble and generate dependencies\n"
|
||||
" -MT file dependency target name\n"
|
||||
" -MQ file dependency target name (quoted)\n"
|
||||
" -MP emit phony target\n\n"
|
||||
" -Zfile redirect error messages to file\n"
|
||||
" -s redirect error messages to stdout\n\n"
|
||||
" -g generate debugging information\n\n"
|
||||
" -F format select a debugging format\n\n"
|
||||
" -gformat same as -g -F format\n\n"
|
||||
" -o outfile write output to an outfile\n\n"
|
||||
" -f format select an output format\n\n"
|
||||
" -l listfile write listing to a listfile\n\n"
|
||||
" -Ipath add a pathname to the include file path\n");
|
||||
printf
|
||||
(" -Olevel optimize opcodes, immediates and branch offsets\n"
|
||||
" -O0 no optimization\n"
|
||||
" -O1 minimal optimization\n"
|
||||
" -Ox multipass optimization (default)\n"
|
||||
" -Pfile pre-include a file (also --include)\n"
|
||||
" -Dmacro[=str] pre-define a macro\n"
|
||||
" -Umacro undefine a macro\n"
|
||||
" -Xformat specifiy error reporting format (gnu or vc)\n"
|
||||
" -w+foo enable warning foo (equiv. -Wfoo)\n"
|
||||
" -w-foo disable warning foo (equiv. -Wno-foo)\n"
|
||||
" -w[+-]error[=foo]\n"
|
||||
" promote [specific] warnings to errors\n"
|
||||
" -h show invocation summary and exit\n\n"
|
||||
" --pragma str pre-executes a specific %%pragma\n"
|
||||
" --before str add line (usually a preprocessor statement) before the input\n"
|
||||
" --prefix str prepend the given string to all the given string\n"
|
||||
" to all extern, common and global symbols\n"
|
||||
" --suffix str append the given string to all the given string\n"
|
||||
" to all extern, common and global symbols\n"
|
||||
" --lprefix str prepend the given string to all other symbols\n"
|
||||
" --limit-X val set execution limit X\n");
|
||||
|
||||
for (i = 0; i <= LIMIT_MAX; i++) {
|
||||
printf(" %-15s %s (default ",
|
||||
limit_info[i].name, limit_info[i].help);
|
||||
if (nasm_limit[i] < LIMIT_MAX_VAL) {
|
||||
printf("%d)\n", nasm_limit[i]);
|
||||
} else {
|
||||
printf("unlimited)\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nWarnings for the -W/-w options:\n");
|
||||
|
||||
for (i = 0; i <= ERR_WARN_ALL; i++)
|
||||
printf(" %-23s %s%s\n",
|
||||
warnings[i].name, warnings[i].help,
|
||||
i == ERR_WARN_ALL ? "\n" :
|
||||
warnings[i].enabled ? " (default on)" :
|
||||
" (default off)");
|
||||
|
||||
if (xopt == 'f') {
|
||||
printf("valid output formats for -f are"
|
||||
" (`*' denotes default):\n");
|
||||
ofmt_list(ofmt, stdout);
|
||||
} else {
|
||||
printf("For a list of valid output formats, use -hf.\n");
|
||||
printf("For a list of debug formats, use -f <format> -y.\n");
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "error.h"
|
||||
|
||||
static enum directive_result asm_pragma(const struct pragma *pragma);
|
||||
static enum directive_result limit_pragma(const struct pragma *pragma);
|
||||
|
||||
/*
|
||||
* Handle [pragma] directives. [pragma] is generally produced by
|
||||
@ -66,6 +67,7 @@ static enum directive_result asm_pragma(const struct pragma *pragma);
|
||||
* so far none of these have any defined pragmas at all:
|
||||
*
|
||||
* preproc - preprocessor
|
||||
* limit - limit setting
|
||||
* asm - assembler
|
||||
* list - listing generator
|
||||
* file - generic file handling
|
||||
@ -86,6 +88,7 @@ static enum directive_result asm_pragma(const struct pragma *pragma);
|
||||
static struct pragma_facility global_pragmas[] =
|
||||
{
|
||||
{ "asm", asm_pragma },
|
||||
{ "limit", limit_pragma },
|
||||
{ "list", NULL },
|
||||
{ "file", NULL },
|
||||
{ "input", NULL },
|
||||
@ -254,3 +257,8 @@ static enum directive_result asm_pragma(const struct pragma *pragma)
|
||||
return DIRR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static enum directive_result limit_pragma(const struct pragma *pragma)
|
||||
{
|
||||
return nasm_set_limit(pragma->opname, pragma->tail);
|
||||
}
|
||||
|
@ -339,12 +339,6 @@ enum {
|
||||
#define NO_DIRECTIVE_FOUND 0
|
||||
#define DIRECTIVE_FOUND 1
|
||||
|
||||
/*
|
||||
* This define sets the upper limit for smacro and recursive mmacro
|
||||
* expansions
|
||||
*/
|
||||
#define DEADMAN_LIMIT (1 << 20)
|
||||
|
||||
/* max reps */
|
||||
#define REP_LIMIT ((INT64_C(1) << 62))
|
||||
|
||||
@ -2875,8 +2869,8 @@ issue_error:
|
||||
return DIRECTIVE_FOUND;
|
||||
}
|
||||
defining = nasm_zalloc(sizeof(MMacro));
|
||||
defining->max_depth =
|
||||
(i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
|
||||
defining->max_depth = ((i == PP_RMACRO) || (i == PP_IRMACRO))
|
||||
? nasm_limit[LIMIT_MACROS] : 0;
|
||||
defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
|
||||
if (!parse_mmacro_spec(tline, defining, pp_directives[i])) {
|
||||
nasm_free(defining);
|
||||
@ -3048,11 +3042,18 @@ issue_error:
|
||||
return DIRECTIVE_FOUND;
|
||||
}
|
||||
count = reloc_value(evalresult);
|
||||
if (count >= REP_LIMIT) {
|
||||
nasm_error(ERR_NONFATAL, "`%%rep' value exceeds limit");
|
||||
if (count > nasm_limit[LIMIT_REP]) {
|
||||
nasm_error(ERR_NONFATAL,
|
||||
"`%%rep' count %"PRId64" exceeds limit (currently %d)",
|
||||
count, nasm_limit[LIMIT_REP]);
|
||||
count = 0;
|
||||
} else
|
||||
} else if (count < 0) {
|
||||
nasm_error(ERR_WARNING|ERR_PASS2|ERR_WARN_NEG_REP,
|
||||
"negative `%%rep' count: %"PRId64, count);
|
||||
count = 0;
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
nasm_error(ERR_NONFATAL, "`%%rep' expects a repeat count");
|
||||
count = 0;
|
||||
@ -4194,7 +4195,7 @@ static Token *expand_smacro(Token * tline)
|
||||
Token *org_tline = tline;
|
||||
Context *ctx;
|
||||
const char *mname;
|
||||
int deadman = DEADMAN_LIMIT;
|
||||
int deadman = nasm_limit[LIMIT_MACROS];
|
||||
bool expanded;
|
||||
|
||||
/*
|
||||
|
@ -112,9 +112,10 @@ static inline vefunc nasm_set_verror(vefunc ve)
|
||||
#define ERR_WARN_UNKNOWN_PRAGMA WARN(18) /* unknown pragma */
|
||||
#define ERR_WARN_NOTMY_PRAGMA WARN(19) /* pragma inapplicable */
|
||||
#define ERR_WARN_UNK_WARNING WARN(20) /* unknown warning */
|
||||
#define ERR_WARN_NEG_REP WARN(21) /* negative repeat count */
|
||||
|
||||
/* The "all" warning acts as a global switch, it must come last */
|
||||
#define ERR_WARN_ALL 21 /* Do not use WARN() here */
|
||||
#define ERR_WARN_ALL 22 /* Do not use WARN() here */
|
||||
|
||||
struct warning {
|
||||
const char *name;
|
||||
|
@ -758,6 +758,22 @@ struct pragma {
|
||||
enum directive opcode; /* Operation as a D_ directives constant */
|
||||
};
|
||||
|
||||
/*
|
||||
* These are semi-arbitrary limits to keep the assembler from going
|
||||
* into a black hole on certain kinds of bugs. They can be overridden
|
||||
* by command-line options or %pragma.
|
||||
*/
|
||||
enum nasm_limit {
|
||||
LIMIT_PASSES,
|
||||
LIMIT_STALLED,
|
||||
LIMIT_MACROS,
|
||||
LIMIT_REP,
|
||||
LIMIT_EVAL
|
||||
};
|
||||
#define LIMIT_MAX LIMIT_EVAL
|
||||
extern int nasm_limit[LIMIT_MAX+1];
|
||||
extern enum directive_result nasm_set_limit(const char *, const char *);
|
||||
|
||||
/*
|
||||
* The data structure defining an output format driver, and the
|
||||
* interfaces to the functions therein.
|
||||
|
@ -180,7 +180,7 @@ size_t pure_func strnlen(const char *, size_t);
|
||||
* Convert a string into a number, using NASM number rules. Sets
|
||||
* `*error' to true if an error occurs, and false otherwise.
|
||||
*/
|
||||
int64_t readnum(char *str, bool *error);
|
||||
int64_t readnum(const char *str, bool *error);
|
||||
|
||||
/*
|
||||
* Convert a character constant into a number. Sets
|
||||
|
@ -65,9 +65,9 @@ static int radix_letter(char c)
|
||||
}
|
||||
}
|
||||
|
||||
int64_t readnum(char *str, bool *error)
|
||||
int64_t readnum(const char *str, bool *error)
|
||||
{
|
||||
char *r = str, *q;
|
||||
const char *r = str, *q;
|
||||
int32_t pradix, sradix, radix;
|
||||
int plen, slen, len;
|
||||
uint64_t result, checklimit;
|
||||
|
Loading…
x
Reference in New Issue
Block a user