Blob Blame History Raw
commit e037dc796de75b0d9e7e893fba6a39c2837aca2b
Author: Serhei Makarov <smakarov@redhat.com>
Date:   Wed Jul 31 13:25:19 2019 -0400

    stapbpf pr23875 bugfix :: allocate actual keysize in foreach to avoid stack clobber
    
    * bpf-translate.cxx (bpf_unparser::visit_foreach_loop): allocate actual keysize.
    * testsuite/systemtap.bpf/bpf_tests/foreach_string.stp: new partial PR23858 testcase,
      added only the parts necessary to trigger a segfault when bugfix not applied.

diff --git a/bpf-translate.cxx b/bpf-translate.cxx
index b254be693..720e23d4e 100644
--- a/bpf-translate.cxx
+++ b/bpf-translate.cxx
@@ -1797,7 +1797,7 @@ bpf_unparser::visit_foreach_loop(foreach_loop* s)
   this_prog.mk_jcond (this_ins, NE, this_prog.lookup_reg(BPF_REG_0), i0,
                       join_block, load_block);
 
-  this_prog.use_tmp_space(16);
+  this_prog.use_tmp_space(2*keysize);
 
   emit_jmp(load_block);
 
diff --git a/testsuite/systemtap.bpf/bpf_tests/foreach_string.stp b/testsuite/systemtap.bpf/bpf_tests/foreach_string.stp
new file mode 100644
index 000000000..956b1b409
--- /dev/null
+++ b/testsuite/systemtap.bpf/bpf_tests/foreach_string.stp
@@ -0,0 +1,119 @@
+global a[10], b[10]
+
+probe begin {
+	printf("BEGIN\n")
+
+	a["p"] = -1
+	a["q"] = 0
+	a["r"] = 1
+
+	b[-1] = "p"
+	b[0] = "q"
+	b[1] = "r"
+
+	exit()
+}
+
+global flag = 1
+global _flag = 1
+
+// XXX Split into separate probes due to stack size constraint.
+global end_probes = 0 // TODO: Remove this workaround for PR24812.
+
+probe end(1) {
+        printf("first end probe\n")
+
+        /* TODO: Requires PR23858.
+	foreach (ks- in a limit -10)
+	  flag = 0
+
+	foreach (ks- in a limit 0)
+	  flag = 0
+
+        found = 0
+        foreach (ks+ in a limit 1) {
+          found++
+          if (a[ks] != -1)
+            flag = 0
+        }
+
+        foreach (k in b+ limit 1) {
+          found++
+          if (k != -1)
+            flag = 0
+        }
+        if (found != 2)
+          flag = 0
+
+	foreach (ks1 in a limit 0)
+	  foreach (ks2 in a)
+	    flag = 0
+
+	foreach (ks1 in a)
+	  foreach (ks2 in a limit 0)
+	    flag = 0
+        */
+
+	x = 0
+	foreach (ks in a)
+	  x += a[ks]
+	flag = flag && x == 0
+
+        if (end_probes == 0)
+          end_probes++
+          // { end_probes++; next; } // TODO: Investigate using next here.
+        else if (flag)
+		printf("END PASS\n")
+	else
+		printf("END FAIL\n")
+}
+
+probe end(2) {
+        printf("second end probe\n")
+
+        /* TODO: Requires PR23858.
+	x = -1
+	foreach (ks+ in a)
+          flag = flag && x++ == a[ks]
+        flag = flag && x == 2
+
+	x = 1
+	foreach (ks- in a)
+        {
+	  flag = flag && x-- == a[ks]
+        }
+        flag = flag && x == -2
+
+        x = -1
+	y = 2
+	foreach (ks1+ in a) {
+	  foreach (k2 in b-)
+          {
+           printf("got %s %d / %d %s\n", ks1, a[ks1], k2, b[k2])
+            flag = flag && x == a[ks1]
+                   && y-- == k2
+          }
+	  x++
+	  y = 2
+	}
+        */
+
+        x = -1
+	y = 1
+        foreach (ks1+ in a) {
+	  foreach (ks2- in a)
+            // TODO: Requires PR23858.
+            _flag = _flag && x == a[ks1]
+                   && y-- == a[ks2]
+	  x++
+	  y = 1
+        }
+
+        if (end_probes == 0)
+          end_probes++
+          // { end_probes++; next; } // TODO: Investigate using next here.
+        else if (flag)
+		printf("END PASS\n")
+	else
+		printf("END FAIL\n")
+}