mirror of
https://github.com/janet-lang/janet
synced 2024-11-29 03:19:54 +00:00
Add JANET_MARSH_UNSAFE flag.
This allows unmarshal to optional marshal raw pointers and cfunctions and send them across threads. This flag is only exposed in the C API as it is very easy to misuse and cause segfaults.
This commit is contained in:
parent
122c77dbf6
commit
5054eb4276
@ -61,7 +61,9 @@ enum {
|
|||||||
LB_ABSTRACT, /* 217 */
|
LB_ABSTRACT, /* 217 */
|
||||||
LB_REFERENCE, /* 218 */
|
LB_REFERENCE, /* 218 */
|
||||||
LB_FUNCENV_REF, /* 219 */
|
LB_FUNCENV_REF, /* 219 */
|
||||||
LB_FUNCDEF_REF /* 220 */
|
LB_FUNCDEF_REF, /* 220 */
|
||||||
|
LB_UNSAFE_CFUNCTION, /* 221 */
|
||||||
|
LB_UNSAFE_POINTER /* 222 */
|
||||||
} LeadBytes;
|
} LeadBytes;
|
||||||
|
|
||||||
/* Helper to look inside an entry in an environment */
|
/* Helper to look inside an entry in an environment */
|
||||||
@ -563,9 +565,25 @@ static void marshal_one(MarshalState *st, Janet x, int flags) {
|
|||||||
marshal_one_fiber(st, janet_unwrap_fiber(x), flags + 1);
|
marshal_one_fiber(st, janet_unwrap_fiber(x), flags + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case JANET_CFUNCTION: {
|
||||||
|
if (!(flags & JANET_MARSHAL_UNSAFE)) goto no_registry;
|
||||||
|
MARK_SEEN();
|
||||||
|
pushbyte(st, LB_UNSAFE_CFUNCTION);
|
||||||
|
JanetCFunction cfn = janet_unwrap_cfunction(x);
|
||||||
|
pushbytes(st, (uint8_t *) &cfn, sizeof(JanetCFunction));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case JANET_POINTER: {
|
||||||
|
if (!(flags & JANET_MARSHAL_UNSAFE)) goto no_registry;
|
||||||
|
MARK_SEEN();
|
||||||
|
pushbyte(st, LB_UNSAFE_POINTER);
|
||||||
|
void *ptr = janet_unwrap_pointer(x);
|
||||||
|
pushbytes(st, (uint8_t *) &ptr, sizeof(void *));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
no_registry:
|
||||||
default: {
|
default: {
|
||||||
janet_panicf("no registry value and cannot marshal %p", x);
|
janet_panicf("no registry value and cannot marshal %p", x);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef MARK_SEEN
|
#undef MARK_SEEN
|
||||||
@ -1293,6 +1311,42 @@ static const uint8_t *unmarshal_one(
|
|||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
case LB_UNSAFE_POINTER: {
|
||||||
|
MARSH_EOS(st, data + sizeof(void *));
|
||||||
|
data++;
|
||||||
|
if (!(flags & JANET_MARSHAL_UNSAFE)) {
|
||||||
|
janet_panicf("unsafe flag not given, "
|
||||||
|
"will not unmarshal raw pointer at index %d",
|
||||||
|
(int)(data - st->start));
|
||||||
|
}
|
||||||
|
union {
|
||||||
|
void *ptr;
|
||||||
|
uint8_t bytes[sizeof(void *)];
|
||||||
|
} u;
|
||||||
|
memcpy(u.bytes, data, sizeof(void *));
|
||||||
|
data += sizeof(void *);
|
||||||
|
*out = janet_wrap_pointer(u.ptr);
|
||||||
|
janet_v_push(st->lookup, *out);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
case LB_UNSAFE_CFUNCTION: {
|
||||||
|
MARSH_EOS(st, data + sizeof(JanetCFunction));
|
||||||
|
data++;
|
||||||
|
if (!(flags & JANET_MARSHAL_UNSAFE)) {
|
||||||
|
janet_panicf("unsafe flag not given, "
|
||||||
|
"will not unmarshal function pointer at index %d",
|
||||||
|
(int)(data - st->start));
|
||||||
|
}
|
||||||
|
union {
|
||||||
|
JanetCFunction ptr;
|
||||||
|
uint8_t bytes[sizeof(JanetCFunction)];
|
||||||
|
} u;
|
||||||
|
memcpy(u.bytes, data, sizeof(JanetCFunction));
|
||||||
|
data += sizeof(JanetCFunction);
|
||||||
|
*out = janet_wrap_cfunction(u.ptr);
|
||||||
|
janet_v_push(st->lookup, *out);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
janet_panicf("unknown byte %x at index %d",
|
janet_panicf("unknown byte %x at index %d",
|
||||||
*data,
|
*data,
|
||||||
|
@ -329,7 +329,7 @@ int janet_thread_send(JanetThread *thread, Janet msg, double timeout) {
|
|||||||
msgbuf->count = 0;
|
msgbuf->count = 0;
|
||||||
|
|
||||||
/* Start panic zone */
|
/* Start panic zone */
|
||||||
janet_marshal(msgbuf, msg, thread->encode, 0);
|
janet_marshal(msgbuf, msg, thread->encode, JANET_MARSHAL_UNSAFE);
|
||||||
/* End panic zone */
|
/* End panic zone */
|
||||||
|
|
||||||
mailbox->messageNext = (mailbox->messageNext + 1) % mailbox->messageCapacity;
|
mailbox->messageNext = (mailbox->messageNext + 1) % mailbox->messageCapacity;
|
||||||
@ -379,7 +379,7 @@ int janet_thread_receive(Janet *msg_out, double timeout) {
|
|||||||
const uint8_t *nextItem = NULL;
|
const uint8_t *nextItem = NULL;
|
||||||
Janet item = janet_unmarshal(
|
Janet item = janet_unmarshal(
|
||||||
msgbuf->data, msgbuf->count,
|
msgbuf->data, msgbuf->count,
|
||||||
0, janet_thread_get_decode(), &nextItem);
|
JANET_MARSHAL_UNSAFE, janet_thread_get_decode(), &nextItem);
|
||||||
*msg_out = item;
|
*msg_out = item;
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
|
@ -1310,6 +1310,8 @@ typedef JanetBuildConfig(*JanetModconf)(void);
|
|||||||
JANET_API JanetModule janet_native(const char *name, JanetString *error);
|
JANET_API JanetModule janet_native(const char *name, JanetString *error);
|
||||||
|
|
||||||
/* Marshaling */
|
/* Marshaling */
|
||||||
|
#define JANET_MARSHAL_UNSAFE 0x20000
|
||||||
|
|
||||||
JANET_API void janet_marshal(
|
JANET_API void janet_marshal(
|
||||||
JanetBuffer *buf,
|
JanetBuffer *buf,
|
||||||
Janet x,
|
Janet x,
|
||||||
|
Loading…
Reference in New Issue
Block a user