[PATCH] Crash during expression optimization

Samuel Thibault samuel.thibault at ens-lyon.org
Mon Sep 29 11:58:36 PDT 2008


Hello,

With the following asm:

begin
A equ 09000h
a	dd 	(A + (end-begin) + 3)
end

The current svn tree crashes.  What happens is that during optimization
the expression above gets flattened at some point, but the result
takes actually less expression terms than before thanks to constant
folding. The problem is that the replacement is done in place and so
some values get overwritten, leading to a mess. I've attached a patch
that fixes this by just allocating a new expression and copy items into
it.

Samuel
-------------- next part --------------
Index: libyasm/expr.c
===================================================================
--- libyasm/expr.c	(r?vision 2121)
+++ libyasm/expr.c	(copie de travail)
@@ -620,7 +620,8 @@
               int simplify_ident, int simplify_reg_mul)
 {
     int i, j, o, fold_numterms, level_numterms, level_fold_numterms;
-    int first_int_term = -1;
+    int first_int_term = -1, first_int_term_out = -1;
+    yasm_expr *e2;
 
     /* Determine how many operands will need to be brought up (for leveling).
      * Go ahead and bring up any IDENT'ed values.
@@ -724,6 +725,8 @@
         return e;
     }
 
+    e->numterms = fold_numterms;
+
     /* Adjust numterms for constant folding from terms being "pulled up".
      * Careful: if there's no integer term in e, then save space for it.
      */
@@ -734,14 +737,23 @@
     }
 
     /* Alloc more (or conceivably less, but not usually) space for e */
-    e = yasm_xrealloc(e, sizeof(yasm_expr)+((level_numterms<2) ? 0 :
+    e2 = yasm_xmalloc(sizeof(yasm_expr)+((level_numterms<2) ? 0 :
                       sizeof(yasm_expr__item)*(level_numterms-2)));
 
+    e2->op = e->op;
+    e2->line = e->line;
+    if (first_int_term != -1) {
+        first_int_term_out = 0;
+        e2->terms[first_int_term_out] = e->terms[first_int_term];
+    }
+
     /* Copy up ExprItem's.  Iterate from right to left to keep the same
      * ordering as was present originally.
      * Combine integer terms as necessary.
      */
     for (i=e->numterms-1, o=level_numterms-1; i>=0; i--) {
+        if (i == first_int_term)
+            continue;
         if (e->terms[i].type == YASM_EXPR_EXPR &&
             e->terms[i].data.expn->op == e->op) {
             /* bring up subexpression */
@@ -753,50 +765,39 @@
                     /* Need to fold it in.. but if there's no int term already,
                      * just copy into a new one.
                      */
-                    if (first_int_term == -1) {
-                        first_int_term = o--;
-                        e->terms[first_int_term] = sube->terms[j];  /* struc */
+                    if (first_int_term_out == -1) {
+                        first_int_term_out = o--;
+                        e2->terms[first_int_term_out] = sube->terms[j];  /* struc */
                     } else {
-                        yasm_intnum_calc(e->terms[first_int_term].data.intn,
+                        yasm_intnum_calc(e2->terms[first_int_term_out].data.intn,
                                          e->op, sube->terms[j].data.intn);
                         /* make sure to delete folded intnum */
                         yasm_intnum_destroy(sube->terms[j].data.intn);
                     }
-                } else {
-                    if (o == first_int_term)
-                        o--;
-                    e->terms[o--] = sube->terms[j];     /* structure copy */
-                }
+                } else
+                    e2->terms[o--] = sube->terms[j];     /* structure copy */
             }
 
             /* delete subexpression, but *don't delete nodes* (as we've just
              * copied them!)
              */
             yasm_xfree(sube);
-        } else if (o != i) {
-            /* copy operand if it changed places */
-            if (o == first_int_term)
-                o--;
-            e->terms[o] = e->terms[i];
-            /* If we moved the first_int_term, change first_int_num too */
-            if (i == first_int_term)
-                first_int_term = o;
-            o--;
         } else
-            o--;
+            e2->terms[o--] = e->terms[i];
     }
 
     /* Simplify identities, make IDENT if possible, and save to e->numterms. */
-    if (simplify_ident && first_int_term != -1) {
-        e->numterms = expr_simplify_identity(e, level_numterms,
-                                             first_int_term, simplify_reg_mul);
+    if (simplify_ident && first_int_term_out != -1) {
+        e2->numterms = expr_simplify_identity(e2, level_numterms,
+                                             first_int_term_out, simplify_reg_mul);
     } else {
-        e->numterms = level_numterms;
+        e2->numterms = level_numterms;
         if (level_numterms == 1)
-            e->op = YASM_EXPR_IDENT;
+            e2->op = YASM_EXPR_IDENT;
     }
 
-    return e;
+    yasm_xfree(e);
+    return e2;
 }
 /*@=mustfree@*/
 


More information about the yasm-devel mailing list