Example #1
0
DUK_EXTERNAL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hbuffer_dynamic *h;
	void *ptr;
	duk_size_t sz;

	DUK_ASSERT(ctx != NULL);

	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
	DUK_ASSERT(h != NULL);

	if (!DUK_HBUFFER_HAS_DYNAMIC(h)) {
		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, DUK_STR_BUFFER_NOT_DYNAMIC);
	}

	/* Forget the previous allocation, setting size to 0 and alloc to
	 * NULL.  Caller is responsible for freeing the previous allocation.
	 * Getting the allocation and clearing it is done in the same API
	 * call to avoid any chance of a realloc.
	 */
	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
	if (out_size) {
		*out_size = sz;
	}
	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
	DUK_HBUFFER_DYNAMIC_SET_ALLOC_SIZE(h, 0);

	return ptr;
}
Example #2
0
DUK_EXTERNAL void duk_config_buffer(duk_context *ctx, duk_idx_t idx, void *ptr, duk_size_t len) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hbuffer_external *h;

	DUK_ASSERT(ctx != NULL);

	h = (duk_hbuffer_external *) duk_require_hbuffer(ctx, idx);
	DUK_ASSERT(h != NULL);

	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
	}
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));

	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
}
Example #3
0
void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hbuffer_dynamic *h;

	DUK_ASSERT(ctx != NULL);

	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
	DUK_ASSERT(h != NULL);

	if (!DUK_HBUFFER_HAS_DYNAMIC(h)) {
		DUK_ERROR(thr, DUK_ERR_TYPE_ERROR, "buffer is not dynamic");
	}

	/* maximum size check is handled by callee */
	duk_hbuffer_resize(thr, h, new_size, new_size);  /* snug */

	return DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h);
}
Example #4
0
DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t new_size) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hbuffer_dynamic *h;

	DUK_ASSERT_CTX_VALID(ctx);

	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, idx);
	DUK_ASSERT(h != NULL);

	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
	}

	/* maximum size check is handled by callee */
	duk_hbuffer_resize(thr, h, new_size);

	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
}
Example #5
0
void duk_to_fixed_buffer(duk_context *ctx, duk_idx_t index) {
	duk_hbuffer_dynamic *h_src;
	duk_uint8_t *data;
	duk_size_t size;

	index = duk_require_normalize_index(ctx, index);

	h_src = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
	DUK_ASSERT(h_src != NULL);
	if (!DUK_HBUFFER_HAS_DYNAMIC(h_src)) {
		return;
	}

	size = DUK_HBUFFER_GET_SIZE(h_src);
	data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, size);
	if (size > 0U) {
		DUK_ASSERT(data != NULL);
		DUK_MEMCPY(data, DUK_HBUFFER_DYNAMIC_GET_CURR_DATA_PTR(h_src), size);
	}

	duk_replace(ctx, index);
}
void duk_regexp_compile(duk_hthread *thr) {
	duk_context *ctx = (duk_context *) thr;
	duk_re_compiler_ctx re_ctx;
	duk_lexer_point lex_point;
	duk_hstring *h_pattern;
	duk_hstring *h_flags;
	duk_hbuffer_dynamic *h_buffer;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(ctx != NULL);

	/*
	 *  Args validation
	 */

	/* TypeError if fails */
	h_pattern = duk_require_hstring(ctx, -2);
	h_flags = duk_require_hstring(ctx, -1);

	/*
	 *  Create normalized 'source' property (E5 Section 15.10.3).
	 */

	/* [ ... pattern flags ] */

	create_escaped_source(thr, -2);

	/* [ ... pattern flags escaped_source ] */

	/*
	 *  Init compilation context
	 */

	duk_push_dynamic_buffer(ctx, 0);
	h_buffer = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, -1);
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buffer));

	/* [ ... pattern flags escaped_source buffer ] */

	DUK_MEMSET(&re_ctx, 0, sizeof(re_ctx));
	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
	re_ctx.thr = thr;
	re_ctx.lex.thr = thr;
	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
	re_ctx.buf = h_buffer;
	re_ctx.recursion_limit = DUK_RE_COMPILE_RECURSION_LIMIT;
	re_ctx.re_flags = parse_regexp_flags(thr, h_flags);

	DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08x, recursion_limit=%d",
	            (unsigned int) re_ctx.re_flags, (int) re_ctx.recursion_limit);

	/*
	 *  Init lexer
	 */

	lex_point.offset = 0;		/* expensive init, just want to fill window */
	lex_point.line = 1;
	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);

	/*
	 *  Compilation
	 */

	DUK_DPRINT("starting regexp compilation");

	append_u32(&re_ctx, DUK_REOP_SAVE);
	append_u32(&re_ctx, 0);
	(void) parse_disjunction(&re_ctx, 1);  /* 1 = expect eof */
	append_u32(&re_ctx, DUK_REOP_SAVE);
	append_u32(&re_ctx, 1);
	append_u32(&re_ctx, DUK_REOP_MATCH);

	DUK_DPRINT("regexp bytecode size (before header) is %d bytes",
	           (int) DUK_HBUFFER_GET_SIZE(re_ctx.buf));

	/*
	 *  Check for invalid backreferences; note that it is NOT an error
	 *  to back-reference a capture group which has not yet been introduced
	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
	 *  always match!  It IS an error to back-reference a capture group
	 *  which will never be introduced in the pattern.  Thus, we can check
	 *  for such references only after parsing is complete.
	 */

	if (re_ctx.highest_backref > re_ctx.captures) {
		DUK_ERROR(thr, DUK_ERR_SYNTAX_ERROR, "invalid backreference(s)");
	}

	/*
	 *  Emit compiled regexp header: flags, ncaptures
	 *  (insertion order inverted on purpose)
	 */

	insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
	insert_u32(&re_ctx, 0, re_ctx.re_flags);

	DUK_DPRINT("regexp bytecode size (after header) is %d bytes",
	           (int) DUK_HBUFFER_GET_SIZE(re_ctx.buf));
	DUK_DDDPRINT("compiled regexp: %!xO", re_ctx.buf);

	/* [ ... pattern flags escaped_source buffer ] */

	duk_to_string(ctx, -1);  /* coerce to string */

	/* [ ... pattern flags escaped_source bytecode ] */

	/*
	 *  Finalize stack
	 */

	duk_remove(ctx, -4);     /* -> [ ... flags escaped_source bytecode ] */
	duk_remove(ctx, -3);     /* -> [ ... escaped_source bytecode ] */

	DUK_DPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
	           duk_get_tval(ctx, -1), duk_get_tval(ctx, -2));
}