Example #1
0
DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_index) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_tval *tv_val;
	duk_small_int_t throw_flag;
	duk_bool_t rc;

	DUK_ASSERT_CTX_VALID(ctx);

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property put right now (putprop protects
	 * against it internally).
	 */

	tv_obj = duk_require_tval(ctx, obj_index);
	tv_key = duk_require_tval(ctx, -2);
	tv_val = duk_require_tval(ctx, -1);
	throw_flag = duk_is_strict_call(ctx);

	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
	DUK_ASSERT(rc == 0 || rc == 1);

	duk_pop_2(ctx);  /* remove key and value */
	return rc;  /* 1 if property found, 0 otherwise */
}
Example #2
0
int duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) {
	duk_tval *tv;
	int to_string = duk_get_magic(ctx);

	duk_push_this(ctx);
	tv = duk_require_tval(ctx, -1);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_BUFFER(tv)) {
		/* nop */
	} else if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);

		/* Must be a "buffer object", i.e. class "Buffer" */
		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_BUFFER) {
			goto type_error;
		}

		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
	} else {
		goto type_error;
	}

	if (to_string) {
		duk_to_string(ctx, -1);
	}
	return 1;

 type_error:
	return DUK_RET_TYPE_ERROR;
}
Example #3
0
DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t idx) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_tval *tv;
	duk_hobject *h;

	DUK_ASSERT_CTX_VALID(ctx);

	tv = duk_require_tval(ctx, idx);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
			goto type_error;
		}
		return (duk_int_t) ((duk_hnatfunc *) h)->magic;
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
	}

	/* fall through */
 type_error:
	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
	return 0;
}
Example #4
0
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx) {
	duk_tval *tv;

	duk_push_this(ctx);
	tv = duk_require_tval(ctx, -1);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_STRING(tv)) {
		/* return as is */
		return 1;
	} else if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);

		/* Must be a "string object", i.e. class "String" */
		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
			goto type_error;
		}

		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
		DUK_ASSERT(duk_is_string(ctx, -1));

		return 1;
	} else {
		goto type_error;
	}

	/* never here, but fall through */

 type_error:
	return DUK_RET_TYPE_ERROR;
}
Example #5
0
DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_bool_t rc;

	DUK_ASSERT_CTX_VALID(ctx);

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property existence check right now.
	 */

	tv_obj = duk_require_tval(ctx, obj_index);
	tv_key = duk_require_tval(ctx, -1);

	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
	DUK_ASSERT(rc == 0 || rc == 1);

	duk_pop(ctx);  /* remove key */
	return rc;  /* 1 if property found, 0 otherwise */
}
Example #6
0
DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_small_int_t throw_flag;
	duk_bool_t rc;

	DUK_ASSERT_CTX_VALID(ctx);

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property delete right now.
	 */

	tv_obj = duk_require_tval(ctx, obj_index);
	tv_key = duk_require_tval(ctx, -1);
	throw_flag = duk_is_strict_call(ctx);

	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
	DUK_ASSERT(rc == 0 || rc == 1);

	duk_pop(ctx);  /* remove key */
	return rc;
}
Example #7
0
/* Define own property without inheritance looks and such.  This differs from
 * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
 * not invoked by this method.  The caller must be careful to invoke any such
 * behaviors if necessary.
 */
DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hobject *obj;
	duk_hstring *key;

	DUK_ASSERT_CTX_VALID(ctx);

	obj = duk_require_hobject(ctx, obj_index);
	DUK_ASSERT(obj != NULL);
	key = duk_to_hstring(ctx, -2);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);

	duk_hobject_define_property_internal(thr, obj, key, desc_flags);

	duk_pop(ctx);  /* pop key */
}
Example #8
0
DUK_INTERNAL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hobject *obj;
	duk_hstring *key;

	DUK_ASSERT_CTX_VALID(ctx);
	DUK_ASSERT_DISABLE(stridx >= 0);
	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);

	obj = duk_require_hobject(ctx, obj_index);
	DUK_ASSERT(obj != NULL);
	key = DUK_HTHREAD_GET_STRING(thr, stridx);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);

	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
	/* value popped by call */
}
Example #9
0
static int duk_disasm(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
	int res = 0, res2 = 0;
	const char *opstr = NULL;
	ut8 *b = a->cur->user;
	duk_push_global_stash (ctx);
	duk_dup (ctx, 0);  /* timer callback */
	duk_get_prop_string (ctx, -2, "disfun");
	b = a->cur->user = duk_require_tval (ctx, -1);
//	pushBuffer (buf, len);
	if (duk_is_callable(ctx, -1)) {
		int i;
		// duk_push_string (ctx, "TODO 2");
		pushBuffer (buf, len);
		duk_call (ctx, 1);

		// [ size, str ]
		for (i = 0; i<3; i++) {
			duk_dup_top (ctx);
			duk_get_prop_index (ctx, -1, i);
			if (duk_is_number (ctx, -1)) {
				if (res)
				res2 = duk_to_number (ctx, -1);
				else
				res2 = res = duk_to_number (ctx, -1);
			} else if (duk_is_string (ctx, -1)) {
				if (!opstr) {
					opstr = duk_to_string (ctx, -1);
				}
			}
			duk_pop (ctx);
		}
	} else {
		eprintf ("[:(] Is not a function %02x %02x\n", b[0],b[1]);
	}

	// fill op struct
	op->size = res;
	if (!opstr) opstr = "invalid";
	strncpy (op->buf_asm, opstr, sizeof (op->buf_asm));
	r_hex_bin2str (buf, op->size, op->buf_hex);
	return res2;
}
Example #10
0
static int duk_assemble(RAsm *a, RAsmOp *op, const char *str) {
	int i, res = 0;
	// call myasm function if available
	duk_push_global_stash (ctx);
	duk_dup (ctx, 0);  /* timer callback */
	duk_get_prop_string (ctx, -2, "asmfun");
	a->cur->user = duk_require_tval (ctx, -1);
	if (duk_is_callable(ctx, -1)) {
		duk_push_string (ctx, str);
		duk_call (ctx, 1);
		// [ array of bytes ]
		//duk_dup_top (ctx);
		res = duk_get_length (ctx, -1);
		op->size = res;
		for (i=0; i<res; i++) {
			duk_dup_top (ctx);
			duk_get_prop_index (ctx, -2, i);
			op->buf[i] = duk_to_int (ctx, -1);
		}
	}
	if (res<1)
		res = -1;
	return res;
}
Example #11
0
DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
	duk_context *ctx = (duk_hthread *) thr;

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

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED: {
		/* return a specific NaN (although not strictly necessary) */
		duk_double_union du;
		DUK_DBLUNION_SET_NAN(&du);
		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
		return du.d;
	}
	case DUK_TAG_NULL: {
		/* +0.0 */
		return 0.0;
	}
	case DUK_TAG_BOOLEAN: {
		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
			return 1.0;
		}
		return 0.0;
	}
	case DUK_TAG_STRING: {
		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
		duk_push_hstring(ctx, h);
		return duk__tonumber_string_raw(thr);
	}
	case DUK_TAG_OBJECT: {
		/* Note: ToPrimitive(object,hint) == [[DefaultValue]](object,hint),
		 * so use [[DefaultValue]] directly.
		 */
		duk_double_t d;
		duk_push_tval(ctx, tv);
		duk_to_defaultvalue(ctx, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */

		/* recursive call for a primitive value (guaranteed not to cause second
		 * recursion).
		 */
		d = duk_js_tonumber(thr, duk_require_tval(ctx, -1));

		duk_pop(ctx);
		return d;
	}
	case DUK_TAG_BUFFER: {
		/* Coerce like a string.  This makes sense because addition also treats
		 * buffers like strings.
		 */
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
		duk_push_hbuffer(ctx, h);
		duk_to_string(ctx, -1);  /* XXX: expensive, but numconv now expects to see a string */
		return duk__tonumber_string_raw(thr);
	}
	case DUK_TAG_POINTER: {
		/* Coerce like boolean */
		void *p = DUK_TVAL_GET_POINTER(tv);
		return (p != NULL ? 1.0 : 0.0);
	}
	case DUK_TAG_LIGHTFUNC: {
		/* +(function(){}) -> NaN */
		return DUK_DOUBLE_NAN;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
#endif
	default: {
		/* number */
		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
		return DUK_TVAL_GET_DOUBLE(tv);
	}
	}

	DUK_UNREACHABLE();
}
Example #12
0
static int r2plugin(duk_context *ctx) {
	RLibStruct *lib_struct;
	int ret = R_TRUE;
	// args: type, function
	const char *type = duk_require_string (ctx, 0);
	if (strcmp (type, "asm")) {
		eprintf ("TODO: duk.r2plugin only supports 'asm' plugins atm\n");
		return R_FALSE;
	}
	// call function of 2nd parameter, or get object
	if (duk_is_function (ctx, 1)) {
		duk_push_string (ctx, "TODO"); // TODO: this must be the RAsm object to get bits, offset, ..
		duk_call (ctx, 1);
		duk_to_object (ctx, 1);
	}
	if (!duk_is_object (ctx, 1)) {
		eprintf ("Expected object or function\n");
		return R_FALSE;
	}
	duk_to_object (ctx, 1);
	#define ap asm_plugin
	ap = R_NEW0 (RAsmPlugin);

#define GETSTR(x,y,or) \
	duk_dup_top (ctx); \
	duk_get_prop_string (ctx, 1, y); \
	if (or) { \
		const char *str = duk_to_string (ctx, -1); \
		x = mystrdup (str? str: or); \
	} else { \
		x = mystrdup (duk_require_string (ctx, -1)); \
	} \
	duk_pop (ctx);

#define GETINT(x,y,or) \
	duk_dup_top (ctx); \
	duk_get_prop_string (ctx, 1, y); \
	if (or) { \
		x = duk_is_number (ctx, -1)? \
			duk_to_int (ctx, -1): or; \
	} else { \
		x = duk_require_int (ctx, -1); \
	} \
	duk_pop (ctx);

#define GETFUN(x,y) \
	duk_dup_top (ctx); \
	duk_get_prop_string (ctx, 1, y); \
	x = duk_require_tval (ctx, 1); \
	duk_pop (ctx);

	// mandatory
	GETSTR (ap->name, "name", NULL);
	GETSTR (ap->arch, "arch", NULL);
	// optional
	GETSTR (ap->license, "license", "unlicensed");
	GETSTR (ap->desc, "description", "JS Disasm Plugin");
	GETINT (ap->bits, "bits", 32);
	// mandatory unless we handle asm+disasm
	ap->user = duk_require_tval (ctx, -1);
	//ap->user = duk_dup_top (ctx); // clone object inside user
	//GETFUN (ap->user, "disassemble");
	duk_push_global_stash(ctx);
	duk_get_prop_string (ctx, 1, "disassemble");
	duk_put_prop_string(ctx, -2, "disfun"); // TODO: prefix plugin name somehow
	ap->disassemble = duk_disasm;

	duk_push_global_stash(ctx);
	duk_get_prop_string (ctx, 1, "assemble");
	duk_put_prop_string(ctx, -2, "asmfun"); // TODO: prefix plugin name somehow
	ap->assemble = duk_assemble;

#if 0
	duk_get_prop_string (ctx, 1, "disassemble");
	duk_push_string (ctx, "WINRAR");
	duk_call (ctx, 1);
#endif
#if 0
	duk_get_prop_string (ctx, 1, "disassemble");
	void *a = duk_require_tval (ctx, -1);
	if (duk_is_callable (ctx, -1)) {
		ut8 *b = a;
		eprintf ("IS FUNCTION %02x %02x \n", b[0], b[1]);
	} else eprintf ("NOT CALLABLE\n");
	ap->user = a;
	eprintf ("---- %p\n", a);
	duk_push_string (ctx, "F**K YOU");
	//duk_dup_top(ctx);
	//duk_call_method (ctx, 0);
	duk_call (ctx, 1);
	duk_push_tval (ctx, ap->user); // push fun
	duk_push_string (ctx, "WINRAR");
	duk_call (ctx, 1);
	duk_pop (ctx);
#endif

	// TODO: add support to assemble from js too
	//ap->assemble = duk_disasm;
	#define lp lib_struct
	lp = R_NEW0 (RLibStruct);
	lp->type = R_LIB_TYPE_ASM; // TODO resolve from handler
	lp->data = ap;
	r_lib_open_ptr (Gcore->lib, "duktape.js", NULL, lp);
	duk_push_boolean (ctx, ret);
	return 1;
}