/*
 *  Sandboxing example
 *
 *  Uses custom memory allocation functions which keep track of total amount
 *  of memory allocated, imposing a maximum total allocation size.
 */

#include <stdio.h>
#include <stdlib.h>
#include "duktape.h"

/*
 *  Memory allocator which backs to standard library memory functions but
 *  keeps a small header to track current allocation size.
 *
 *  Many other sandbox allocation models are useful, e.g. preallocated pools.
 */

typedef struct {
	/* The double value in the union is there to ensure alignment is
	 * good for IEEE doubles too.  In many 32-bit environments 4 bytes
	 * would be sufficiently aligned and the double value is unnecessary.
	 */
	union {
		size_t sz;
		double d;
	} u;
} alloc_hdr;

static size_t total_allocated = 0;
static size_t max_allocated = 256 * 1024;  /* 256kB sandbox */

static void sandbox_dump_memstate(void) {
#if 0
	fprintf(stderr, "Total allocated: %ld\n", (long) total_allocated);
	fflush(stderr);
#endif
}

static void *sandbox_alloc(void *udata, duk_size_t size) {
	alloc_hdr *hdr;

	(void) udata;  /* Suppress warning. */

	if (size == 0) {
		return NULL;
	}

	if (total_allocated + size > max_allocated) {
		fprintf(stderr, "Sandbox maximum allocation size reached, %ld requested in sandbox_alloc\n",
		        (long) size);
		fflush(stderr);
		return NULL;
	}

	hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr));
	if (!hdr) {
		return NULL;
	}
	hdr->u.sz = size;
	total_allocated += size;
	sandbox_dump_memstate();
	return (void *) (hdr + 1);
}

static void *sandbox_realloc(void *udata, void *ptr, duk_size_t size) {
	alloc_hdr *hdr;
	size_t old_size;
	void *t;

	(void) udata;  /* Suppress warning. */

	/* Handle the ptr-NULL vs. size-zero cases explicitly to minimize
	 * platform assumptions.  You can get away with much less in specific
	 * well-behaving environments.
	 */

	if (ptr) {
		hdr = (alloc_hdr *) (((char *) ptr) - sizeof(alloc_hdr));
		old_size = hdr->u.sz;

		if (size == 0) {
			total_allocated -= old_size;
			free((void *) hdr);
			sandbox_dump_memstate();
			return NULL;
		} else {
			if (total_allocated - old_size + size > max_allocated) {
				fprintf(stderr, "Sandbox maximum allocation size reached, %ld requested in sandbox_realloc\n",
				        (long) size);
				fflush(stderr);
				return NULL;
			}

			t = realloc((void *) hdr, size + sizeof(alloc_hdr));
			if (!t) {
				return NULL;
			}
			hdr = (alloc_hdr *) t;
			total_allocated -= old_size;
			total_allocated += size;
			hdr->u.sz = size;
			sandbox_dump_memstate();
			return (void *) (hdr + 1);
		}
	} else {
		if (size == 0) {
			return NULL;
		} else {
			if (total_allocated + size > max_allocated) {
				fprintf(stderr, "Sandbox maximum allocation size reached, %ld requested in sandbox_realloc\n",
				        (long) size);
				fflush(stderr);
				return NULL;
			}

			hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr));
			if (!hdr) {
				return NULL;
			}
			hdr->u.sz = size;
			total_allocated += size;
			sandbox_dump_memstate();
			return (void *) (hdr + 1);
		}
	}
}

static void sandbox_free(void *udata, void *ptr) {
	alloc_hdr *hdr;

	(void) udata;  /* Suppress warning. */

	if (!ptr) {
		return;
	}
	hdr = (alloc_hdr *) (((char *) ptr) - sizeof(alloc_hdr));
	total_allocated -= hdr->u.sz;
	free((void *) hdr);
	sandbox_dump_memstate();
}

/*
 *  Sandbox setup and test
 */

static duk_ret_t do_sandbox_test(duk_context *ctx) {
	FILE *f;
	char buf[4096];
	size_t ret;
	const char *globobj;

	/*
	 *  Setup sandbox
	 */

	globobj =
		"({\n"
		"    print: print,\n"
		"    Math: {\n"
		"        max: Math.max\n"
		"    }\n"
		"})\n";
#if 1
	fprintf(stderr, "Sandbox global object:\n----------------\n%s----------------\n", globobj);
	fflush(stderr);
#endif
	duk_eval_string(ctx, globobj);
	duk_set_global_object(ctx);

	/*
	 *  Execute code from specified file
	 */

	f = fopen(duk_require_string(ctx, -1), "rb");
	if (!f) {
		duk_error(ctx, DUK_ERR_ERROR, "failed to open file");
	}

	for (;;) {
		if (ferror(f)) {
			fclose(f);
			duk_error(ctx, DUK_ERR_ERROR, "ferror when reading file");
		}
		if (feof(f)) {
			break;
		}

		ret = fread(buf, 1, sizeof(buf), f);
		if (ret == 0) {
			break;
		}

		duk_push_lstring(ctx, (const char *) buf, ret);
	}

	duk_concat(ctx, duk_get_top(ctx) - 1);  /* -1 for filename */

	/* -> [ ... filename source ] */

	duk_insert(ctx, -2);

	/* -> [ ... source filename ] */

	duk_compile(ctx, 0 /*flags*/);  /* Compile as program */
	duk_call(ctx, 0 /*nargs*/);

	return 0;
}

/*
 *  Main
 */

static void sandbox_fatal(duk_context *ctx, duk_errcode_t code, const char *msg) {
	(void) ctx;  /* Suppress warning. */
	fprintf(stderr, "FATAL %ld: %s\n", (long) code, (msg ? msg : "no message"));
	fflush(stderr);
	exit(1);  /* must not return */
}

int main(int argc, char *argv[]) {
	duk_context *ctx;
	duk_int_t rc;

	if (argc < 2) {
		fprintf(stderr, "Usage: sandbox <test.js>\n");
		fflush(stderr);
		exit(1);
	}

	ctx = duk_create_heap(sandbox_alloc,
	                      sandbox_realloc,
	                      sandbox_free,
	                      NULL,
	                      sandbox_fatal);

	duk_push_string(ctx, argv[1]);
	rc = duk_safe_call(ctx, do_sandbox_test, 1 /*nargs*/, 1 /*nrets*/);
	if (rc) {
		fprintf(stderr, "ERROR: %s\n", duk_safe_to_string(ctx, -1));
		fflush(stderr);
	}

	duk_destroy_heap(ctx);

	/* Should be zero. */
	fprintf(stderr, "Final allocation: %ld\n", (long) total_allocated);
	fflush(stderr);

	return 1;
}
