shithub: orca

Download patch

ref: cc3bc3afee0c0fcb3c5f077b150fb0fa96a8cdf6
parent: 08f15762b64a80edd49edef5fd92da9c993408a2
author: cancel <cancel@cancel.fm>
date: Mon Dec 3 06:19:07 EST 2018

Fix buffer bounds check off-by-one

--- a/sim.c
+++ b/sim.c
@@ -74,11 +74,11 @@
 ORCA_PURE ORCA_FORCE_NO_INLINE static bool
 oper_has_neighboring_bang(Glyph const* gbuf, Usz h, Usz w, Usz y, Usz x) {
   Glyph const* gp = gbuf + w * y + x;
-  if (x < w && gp[1] == '*')
+  if (x < w - 1 && gp[1] == '*')
     return true;
   if (x > 0 && *(gp - 1) == '*')
     return true;
-  if (y < h && gp[w] == '*')
+  if (y < h - 1 && gp[w] == '*')
     return true;
   // note: negative array subscript on rhs of short-circuit, may cause ub if
   // the arithmetic under/overflows, even if guarded the guard on lhs is false
@@ -518,13 +518,19 @@
     PORT(0, -1, IN | HASTE);
   END_PORTS
   if (IS_AWAKE && DUAL_IS_ACTIVE) {
-    Usz len = usz_clamp(index_of(PEEK(0, -1)), 1, 16);
+    Usz len = index_of(PEEK(0, -1));
     I32 len_data[1];
     len_data[0] = (I32)len;
     STORE(len_data);
-    // todo optimize
+    if (len == 0)
+      len = 1;
+    else if (len > 16)
+      len = 16;
+    if (len > width - x - 1)
+      len = width - x - 1;
+    Mark* m = mbuffer + y * width + x + 1;
     for (Usz i = 0; i < len; ++i) {
-      LOCK(0, (Isz)i + 1);
+      m[i] |= Mark_flag_lock;
     }
   }
 END_PHASE
@@ -533,13 +539,19 @@
   STOP_IF_DUAL_INACTIVE;
   I32 len_data[1];
   // todo should at least stun the 1 column if columns is 1
-  if (LOAD(len_data) && len_data[0] >= 1 && len_data[0] <= 16) {
+  if (LOAD(len_data) && len_data[0] >= 0) {
     Usz len = (Usz)len_data[0];
+    if (len > width - x - 1)
+      len = width - x - 1;
+    if (len == 0)
+      return;
+    if (len > 16)
+      len = 16;
     Glyph buff[16];
     Glyph* gs = gbuffer + y * width + x + 1;
     Glyph hopped = *gs;
     // ORCA_MEMCPY(buff, gs + 1, len - 1);
-    for (Usz i = 0; i < len - 1; ++i) {
+    for (Usz i = 0; i < len; ++i) {
       buff[i] = gs[i + 1];
     }
     buff[len - 1] = hopped;
@@ -547,8 +559,9 @@
     for (Usz i = 0; i < len; ++i) {
       gs[i] = buff[i];
     }
+    Mark* m = mbuffer + y * width + x + 1;
     for (Usz i = 0; i < len; ++i) {
-      STUN(0, (Isz)i + 1);
+      *m |= Mark_flag_sleep;
     }
   }
 END_PHASE