summaryrefslogtreecommitdiff
path: root/asm/parser.c
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@gmail.com>2018-10-15 22:58:13 +0300
committerCyrill Gorcunov <gorcunov@gmail.com>2018-10-15 22:58:13 +0300
commitf7b44f6092623df2a84b5db317d0c5217eccd87e (patch)
tree8489eb0ff19b98281c697b636e00cb70a1a5c681 /asm/parser.c
parent94adf7d765a06d6608ca3aa317ac69a332c817cf (diff)
parent28b69e2a633a850e724f309a5ec81bac8638084a (diff)
downloadnasm-f7b44f6092623df2a84b5db317d0c5217eccd87e.tar.gz
Merge branch 'nasm-2.14.xx'
* nasm-2.14.xx: (83 commits) NASM 2.14rc16 doc: Update changes preproc: expand_smacro -- Fix nil dereference on error path eval: Eliminate division by zero doc: Update changes opflags: Convert is_class and is_reg_class to helpers preproc: Fix out of range access in expand mmacro doc: Update changes parser: Fix sigsegv on certain equ instruction parsing labels: Make sure nil label is never passed labels: Don't nil dereference if no label provided macho: Add warning message in macho_output() macho/reloc: Fix addr size sensitive conditions macho/reloc: Fix macho_output() to get the offset adjustments by add_reloc() macho/reloc: Fixed offset adjustment in add_reloc() macho/reloc: Allow absolute relocation when forcing a symbol reference macho/reloc: Adjust SUB relocation information macho/reloc: Fixed in handling GOT/GOTLOAD/TLV relocations macho/reloc: Simplified relocation for REL/BRANCH macho/sym: Record initial symbol number always ... Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Diffstat (limited to 'asm/parser.c')
-rw-r--r--asm/parser.c54
1 files changed, 47 insertions, 7 deletions
diff --git a/asm/parser.c b/asm/parser.c
index d5a45753..78f347fa 100644
--- a/asm/parser.c
+++ b/asm/parser.c
@@ -486,7 +486,8 @@ restart_parse:
* Generally fix things. I think this is right as it is, but
* am still not certain.
*/
- define_label(result->label, location.segment,
+ define_label(result->label,
+ in_absolute ? absolute.segment : location.segment,
location.offset, true);
}
}
@@ -1027,7 +1028,7 @@ is_expression:
op->segment = NO_SEG; /* don't care again */
op->wrt = NO_SEG; /* still don't care */
- if(optimizing >= 0 && !(op->type & STRICT)) {
+ if(optimizing.level >= 0 && !(op->type & STRICT)) {
/* Be optimistic */
op->type |=
UNITY | SBYTEWORD | SBYTEDWORD | UDWORD | SDWORD;
@@ -1044,7 +1045,7 @@ is_expression:
if (is_simple(value)) {
if (n == 1)
op->type |= UNITY;
- if (optimizing >= 0 && !(op->type & STRICT)) {
+ if (optimizing.level >= 0 && !(op->type & STRICT)) {
if ((uint32_t) (n + 128) <= 255)
op->type |= SBYTEDWORD;
if ((uint16_t) (n + 128) <= 255)
@@ -1077,6 +1078,7 @@ is_expression:
}
} else { /* it's a register */
opflags_t rs;
+ uint64_t regset_size = 0;
if (value->type >= EXPR_SIMPLE || value->value != 1) {
nasm_error(ERR_NONFATAL, "invalid operand type");
@@ -1084,13 +1086,32 @@ is_expression:
}
/*
- * check that its only 1 register, not an expression...
+ * We do not allow any kind of expression, except for
+ * reg+value in which case it is a register set.
*/
- for (i = 1; value[i].type; i++)
- if (value[i].value) {
+ for (i = 1; value[i].type; i++) {
+ if (!value[i].value)
+ continue;
+
+ switch (value[i].type) {
+ case EXPR_SIMPLE:
+ if (!regset_size) {
+ regset_size = value[i].value + 1;
+ break;
+ }
+ /* fallthrough */
+ default:
nasm_error(ERR_NONFATAL, "invalid operand type");
goto fail;
}
+ }
+
+ if ((regset_size & (regset_size - 1)) ||
+ regset_size >= (UINT64_C(1) << REGSET_BITS)) {
+ nasm_error(ERR_NONFATAL | ERR_PASS2,
+ "invalid register set size");
+ regset_size = 0;
+ }
/* clear overrides, except TO which applies to FPU regs */
if (op->type & ~TO) {
@@ -1099,12 +1120,31 @@ is_expression:
* is different from the register size
*/
rs = op->type & SIZE_MASK;
- } else
+ } else {
rs = 0;
+ }
+
+ /*
+ * Make sure we're not out of nasm_reg_flags, still
+ * probably this should be fixed when we're defining
+ * the label.
+ *
+ * An easy trigger is
+ *
+ * e equ 0x80000000:0
+ * pshufw word e-0
+ *
+ */
+ if (value->type < EXPR_REG_START ||
+ value->type > EXPR_REG_END) {
+ nasm_error(ERR_NONFATAL, "invalid operand type");
+ goto fail;
+ }
op->type &= TO;
op->type |= REGISTER;
op->type |= nasm_reg_flags[value->type];
+ op->type |= (regset_size >> 1) << REGSET_SHIFT;
op->decoflags |= brace_flags;
op->basereg = value->type;