summary refs log tree commit diff stats
path: root/tinyc/tests/vla_test.c
diff options
context:
space:
mode:
authorDmitry Atamanov <data-man@users.noreply.github.com>2017-10-28 10:25:56 +0300
committerAndreas Rumpf <rumpf_a@web.de>2017-10-28 09:25:56 +0200
commitd2c7d391c8b69a6a590a2f702ed58bea033f6325 (patch)
treec74a1b46e1166ddb87453ddc49cea84e1baaa5ab /tinyc/tests/vla_test.c
parent9c00f6decd4453a4233450a60ccef05b20e9f24a (diff)
downloadNim-d2c7d391c8b69a6a590a2f702ed58bea033f6325.tar.gz
TinyC upgrade (#6593)
Diffstat (limited to 'tinyc/tests/vla_test.c')
-rw-r--r--tinyc/tests/vla_test.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/tinyc/tests/vla_test.c b/tinyc/tests/vla_test.c
new file mode 100644
index 000000000..3616c46d4
--- /dev/null
+++ b/tinyc/tests/vla_test.c
@@ -0,0 +1,84 @@
+/*
+ * Test that allocating a variable length array in a loop
+ * does not use up a linear amount of memory
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define LOOP_COUNT 1000
+#define ARRAY_SIZE 100
+
+/* Overwrite a VLA. This will overwrite the return address if SP is incorrect */
+void smash(char *p, int n) {
+  memset(p, 0, n);
+}
+
+int test1(int n) {
+  int i;
+  char *array_ptrs[LOOP_COUNT];
+  
+  for (i = 0; i < LOOP_COUNT; ++i) {
+    char test[n];
+    smash(test, n);
+    array_ptrs[i] = test;
+  }
+  
+  return (array_ptrs[0]-array_ptrs[LOOP_COUNT-1] < n) ? 0 : 1;
+}
+
+/* ensure goto does not circumvent array free */
+int test2(int n) {
+  char *array_ptrs[LOOP_COUNT];
+
+  int i = 0;
+loop:;
+  char test[n];
+  smash(test, n);
+  if (i >= LOOP_COUNT)
+    goto end;
+  array_ptrs[i] = test;
+  ++i;
+  goto loop;
+
+end:
+  smash(test, n);
+  char test2[n];
+  smash(test2, n);
+  return (array_ptrs[0] - array_ptrs[LOOP_COUNT-1] < n) ? 0 : 1;
+}
+
+int test3(int n) {
+  char test[n];
+  smash(test, n);
+  goto label;
+label:
+  smash(test, n);
+  char test2[n];
+  smash(test2, n);
+  return (test-test2 >= n) ? 0 : 1;
+}
+
+#define RUN_TEST(t) \
+  if (!testname || (strcmp(#t, testname) == 0)) { \
+    fputs(#t "... ", stdout); \
+    fflush(stdout); \
+    if (t(ARRAY_SIZE) == 0) { \
+      fputs("success\n", stdout); \
+    } else { \
+      fputs("failure\n", stdout); \
+      retval = EXIT_FAILURE; \
+    } \
+  }
+
+int main(int argc, char **argv) {
+  const char *testname = NULL;
+  int retval = EXIT_SUCCESS;
+  if (argc > 1)
+    testname = argv[1];
+  RUN_TEST(test1)
+  RUN_TEST(test2)
+  RUN_TEST(test3)
+  return retval;
+}