aboutsummaryrefslogtreecommitdiffstats
path: root/cint_array.c
diff options
context:
space:
mode:
Diffstat (limited to 'cint_array.c')
-rw-r--r--cint_array.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/cint_array.c b/cint_array.c
index 08815e4e..417f27d5 100644
--- a/cint_array.c
+++ b/cint_array.c
@@ -73,6 +73,24 @@ const array_funcs_t cint_array_func = {
(afunc_t) 0,
};
+
+static NODE **argv_store(NODE *symbol, NODE *subs);
+
+/* special case for ARGV in sandbox mode */
+const array_funcs_t argv_array_func = {
+ "argv",
+ cint_array_init,
+ is_uinteger,
+ cint_lookup,
+ cint_exists,
+ cint_clear,
+ cint_remove,
+ cint_list,
+ cint_copy,
+ cint_dump,
+ argv_store,
+};
+
static inline int cint_hash(long k);
static inline NODE **cint_find(NODE *symbol, long k, int h1);
@@ -1230,3 +1248,68 @@ leaf_print(NODE *array, size_t bi, int indent_level)
(unsigned long) array->table_size);
}
#endif
+
+static NODE *argv_shadow_array = NULL;
+
+/* argv_store --- post assign function for ARGV in sandbox mode */
+
+static NODE **
+argv_store(NODE *symbol, NODE *subs)
+{
+ NODE **val = cint_exists(symbol, subs);
+ NODE *newval = *val;
+ char *cp;
+
+ if (newval->stlen == 0) // empty strings in ARGV are OK
+ return val;
+
+ if ((cp = strchr(newval->stptr, '=')) == NULL) {
+ if (! in_array(argv_shadow_array, newval))
+ fatal(_("cannot add a new file (%.*s) to ARGV in sandbox mode"),
+ (int) newval->stlen, newval->stptr);
+ } else {
+ // check if it's a valid variable assignment
+ bool badvar = false;
+ char *arg = newval->stptr;
+ char *cp2;
+
+ *cp = '\0'; // temporarily
+
+ if (! is_letter((unsigned char) arg[0]))
+ badvar = true;
+ else
+ for (cp2 = arg+1; *cp2; cp2++)
+ if (! is_identchar((unsigned char) *cp2) && *cp2 != ':') {
+ badvar = true;
+ break;
+ }
+
+ // further checks
+ if (! badvar) {
+ char *cp = strchr(arg, ':');
+ if (cp && (cp[1] != ':' || strchr(cp + 2, ':') != NULL))
+ badvar = true;
+ }
+ *cp = '='; // restore the '='
+
+ if (badvar && ! in_array(argv_shadow_array, newval))
+ fatal(_("cannot add a new file (%.*s) to ARGV in sandbox mode"),
+ (int) newval->stlen, newval->stptr);
+
+ // otherwise, badvar is false, let it through as variable assignment
+ }
+ return val;
+}
+
+/* init_argv_array --- set up the pointers for ARGV in sandbox mode. A bit hacky. */
+
+void
+init_argv_array(NODE *argv_node, NODE *shadow_node)
+{
+ /* If POSIX simply don't reset the vtable and things work as before */
+ if (! do_sandbox)
+ return;
+
+ argv_node->array_funcs = & argv_array_func;
+ argv_shadow_array = shadow_node;
+}