wasm bindings: enforce pointer length
* bindgen.py: print an error when a pointer argument doesn't have an annotated length * ensure all bindings with pointers have length annotations * add a couple helper functions for dealing with length annotations
This commit is contained in:
parent
9b3a71a5c8
commit
15a8e2ae22
|
@ -11,6 +11,11 @@ def needs_arg_ptr_stub(decl):
|
||||||
res = True
|
res = True
|
||||||
return(res)
|
return(res)
|
||||||
|
|
||||||
|
def printError(str):
|
||||||
|
# This prints a string with a red foreground color.
|
||||||
|
# See this link for an explanation of console escape codes: https://stackabuse.com/how-to-print-colored-text-in-python/
|
||||||
|
print("\x1b[38;5;196m" + "error: " + str + "\033[0;0m")
|
||||||
|
|
||||||
|
|
||||||
def bindgen(apiName, spec, **kwargs):
|
def bindgen(apiName, spec, **kwargs):
|
||||||
guest_stubs_path = kwargs.get("guest_stubs")
|
guest_stubs_path = kwargs.get("guest_stubs")
|
||||||
|
@ -152,37 +157,39 @@ def bindgen(apiName, spec, **kwargs):
|
||||||
argTag = arg['type']['tag']
|
argTag = arg['type']['tag']
|
||||||
argLen = arg.get('len')
|
argLen = arg.get('len')
|
||||||
|
|
||||||
if argTag == 'p' and argLen != None:
|
if argTag == 'p':
|
||||||
|
if argLen == None:
|
||||||
s += '\t{\n'
|
printError("binding '" + name + "' missing pointer length decoration for param '" + argName + "'")
|
||||||
s += '\t\tOC_ASSERT(((char*)'+ argName + ' >= (char*)_mem) && (((char*)'+ argName +' - (char*)_mem) < m3_GetMemorySize(runtime)), "parameter \''+argName+'\' is out of bounds");\n'
|
|
||||||
s += '\t\tOC_ASSERT((char*)' + argName + ' + '
|
|
||||||
|
|
||||||
proc = argLen.get('proc')
|
|
||||||
if proc != None:
|
|
||||||
s += proc + '(runtime, '
|
|
||||||
lenProcArgs = argLen['args']
|
|
||||||
for i, lenProcArg in enumerate(lenProcArgs):
|
|
||||||
s += lenProcArg
|
|
||||||
if i < len(lenProcArgs)-1:
|
|
||||||
s += ', '
|
|
||||||
s += ')'
|
|
||||||
else:
|
else:
|
||||||
components = argLen.get('components')
|
s += '\t{\n'
|
||||||
countArg = argLen.get('count')
|
s += '\t\tOC_ASSERT(((char*)'+ argName + ' >= (char*)_mem) && (((char*)'+ argName +' - (char*)_mem) < m3_GetMemorySize(runtime)), "parameter \''+argName+'\' is out of bounds");\n'
|
||||||
|
s += '\t\tOC_ASSERT((char*)' + argName + ' + '
|
||||||
|
|
||||||
if components != None:
|
proc = argLen.get('proc')
|
||||||
s += str(components)
|
if proc != None:
|
||||||
|
s += proc + '(runtime, '
|
||||||
|
lenProcArgs = argLen['args']
|
||||||
|
for i, lenProcArg in enumerate(lenProcArgs):
|
||||||
|
s += lenProcArg
|
||||||
|
if i < len(lenProcArgs)-1:
|
||||||
|
s += ', '
|
||||||
|
s += ')'
|
||||||
|
else:
|
||||||
|
components = argLen.get('components')
|
||||||
|
countArg = argLen.get('count')
|
||||||
|
|
||||||
|
if components != None:
|
||||||
|
s += str(components)
|
||||||
|
if countArg != None:
|
||||||
|
s += '*'
|
||||||
if countArg != None:
|
if countArg != None:
|
||||||
s += '*'
|
s += countArg
|
||||||
if countArg != None:
|
|
||||||
s += countArg
|
|
||||||
|
|
||||||
if typeCName.endswith('**') or (typeCName.startswith('void') == False and typeCName.startswith('const void') == False):
|
if typeCName.endswith('**') or (typeCName.startswith('void') == False and typeCName.startswith('const void') == False):
|
||||||
s += '*sizeof('+typeCName[:-1]+')'
|
s += '*sizeof('+typeCName[:-1]+')'
|
||||||
|
|
||||||
s += ' <= ((char*)_mem + m3_GetMemorySize(runtime)), "parameter \''+argName+'\' overflows wasm memory");\n'
|
s += ' <= ((char*)_mem + m3_GetMemorySize(runtime)), "parameter \''+argName+'\' overflows wasm memory");\n'
|
||||||
s += '\t}\n'
|
s += '\t}\n'
|
||||||
|
|
||||||
s += '\t'
|
s += '\t'
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,25 @@ oc_str8 oc_runtime_get_wasm_memory()
|
||||||
return (mem);
|
return (mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 orca_check_cstring(IM3Runtime runtime, const char* ptr)
|
||||||
|
{
|
||||||
|
uint32_t memorySize = 0;
|
||||||
|
char* memory = (char*)m3_GetMemory(runtime, &memorySize, 0);
|
||||||
|
|
||||||
|
//NOTE: Here we are guaranteed that ptr is in [ memory ; memory + memorySize [
|
||||||
|
// hence (memory + memorySize) - ptr is representable by size_t and <= memorySize
|
||||||
|
size_t maxLen = (memory + memorySize) - ptr;
|
||||||
|
|
||||||
|
u64 len = strnlen(ptr, maxLen);
|
||||||
|
|
||||||
|
if(len == maxLen)
|
||||||
|
{
|
||||||
|
//NOTE: string overflows wasm memory, return a length that will trigger the bounds check
|
||||||
|
len = maxLen + 1;
|
||||||
|
}
|
||||||
|
return (len + 1); //include null-terminator
|
||||||
|
}
|
||||||
|
|
||||||
void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg)
|
void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg)
|
||||||
{
|
{
|
||||||
M3ErrorInfo errInfo = { 0 };
|
M3ErrorInfo errInfo = { 0 };
|
||||||
|
@ -99,13 +118,13 @@ void oc_bridge_window_set_size(oc_vec2 size)
|
||||||
}
|
}
|
||||||
|
|
||||||
void oc_bridge_log(oc_log_level level,
|
void oc_bridge_log(oc_log_level level,
|
||||||
int fileLen,
|
int fileLen,
|
||||||
char* file,
|
char* file,
|
||||||
int functionLen,
|
int functionLen,
|
||||||
char* function,
|
char* function,
|
||||||
int line,
|
int line,
|
||||||
int msgLen,
|
int msgLen,
|
||||||
char* msg)
|
char* msg)
|
||||||
{
|
{
|
||||||
oc_debug_overlay* debug = &__orcaApp.debugOverlay;
|
oc_debug_overlay* debug = &__orcaApp.debugOverlay;
|
||||||
|
|
||||||
|
@ -349,6 +368,7 @@ void oc_wasm_env_init(oc_wasm_env* runtime)
|
||||||
#include "wasmbind/gles_api_bind_manual.c"
|
#include "wasmbind/gles_api_bind_manual.c"
|
||||||
#include "wasmbind/gles_api_bind_gen.c"
|
#include "wasmbind/gles_api_bind_gen.c"
|
||||||
#include "wasmbind/io_api_bind_gen.c"
|
#include "wasmbind/io_api_bind_gen.c"
|
||||||
|
#include "wasmbind/surface_api_bind_manual.c"
|
||||||
#include "wasmbind/surface_api_bind_gen.c"
|
#include "wasmbind/surface_api_bind_gen.c"
|
||||||
|
|
||||||
i32 orca_runloop(void* user)
|
i32 orca_runloop(void* user)
|
||||||
|
|
|
@ -8,17 +8,20 @@
|
||||||
{"name": "fileLen",
|
{"name": "fileLen",
|
||||||
"type": {"name": "int", "tag": "i"}},
|
"type": {"name": "int", "tag": "i"}},
|
||||||
{"name": "file",
|
{"name": "file",
|
||||||
"type": {"name": "char*", "tag": "p"}},
|
"type": {"name": "char*", "tag": "p"},
|
||||||
|
"len": {"count": "fileLen"}},
|
||||||
{"name": "functionLen",
|
{"name": "functionLen",
|
||||||
"type": {"name": "int", "tag": "i"}},
|
"type": {"name": "int", "tag": "i"}},
|
||||||
{"name": "function",
|
{"name": "function",
|
||||||
"type": {"name": "char*", "tag": "p"}},
|
"type": {"name": "char*", "tag": "p"},
|
||||||
|
"len": {"count": "functionLen"}},
|
||||||
{"name": "line",
|
{"name": "line",
|
||||||
"type": {"name": "int", "tag": "i"}},
|
"type": {"name": "int", "tag": "i"}},
|
||||||
{"name": "msgLen",
|
{"name": "msgLen",
|
||||||
"type": {"name": "int", "tag": "i"}},
|
"type": {"name": "int", "tag": "i"}},
|
||||||
{"name": "msg",
|
{"name": "msg",
|
||||||
"type": {"name": "char*", "tag": "p"}}
|
"type": {"name": "char*", "tag": "p"},
|
||||||
|
"len": {"count": "msgLen"}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -33,15 +36,19 @@
|
||||||
"cname": "oc_assert_fail",
|
"cname": "oc_assert_fail",
|
||||||
"ret": {"name": "void", "tag": "v"},
|
"ret": {"name": "void", "tag": "v"},
|
||||||
"args": [ {"name": "file",
|
"args": [ {"name": "file",
|
||||||
"type": {"name": "const char*", "tag": "p"}},
|
"type": {"name": "const char*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_check_cstring", "args": ["file"]}},
|
||||||
{"name": "function",
|
{"name": "function",
|
||||||
"type": {"name": "const char*", "tag": "p"}},
|
"type": {"name": "const char*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_check_cstring", "args": ["function"]}},
|
||||||
{"name": "line",
|
{"name": "line",
|
||||||
"type": {"name": "int", "tag": "i"}},
|
"type": {"name": "int", "tag": "i"}},
|
||||||
{"name": "src",
|
{"name": "src",
|
||||||
"type": {"name": "const char*", "tag": "p"}},
|
"type": {"name": "const char*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_check_cstring", "args": ["src"]}},
|
||||||
{"name": "note",
|
{"name": "note",
|
||||||
"type": {"name": "const char*", "tag": "p"}}
|
"type": {"name": "const char*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_check_cstring", "args": ["note"]}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -49,13 +56,16 @@
|
||||||
"cname": "oc_abort_ext",
|
"cname": "oc_abort_ext",
|
||||||
"ret": {"name": "void", "tag": "v"},
|
"ret": {"name": "void", "tag": "v"},
|
||||||
"args": [ {"name": "file",
|
"args": [ {"name": "file",
|
||||||
"type": {"name": "const char*", "tag": "p"}},
|
"type": {"name": "const char*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_check_cstring", "args": ["file"]}},
|
||||||
{"name": "function",
|
{"name": "function",
|
||||||
"type": {"name": "const char*", "tag": "p"}},
|
"type": {"name": "const char*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_check_cstring", "args": ["function"]}},
|
||||||
{"name": "line",
|
{"name": "line",
|
||||||
"type": {"name": "int", "tag": "i"}},
|
"type": {"name": "int", "tag": "i"}},
|
||||||
{"name": "note",
|
{"name": "note",
|
||||||
"type": {"name": "const char*", "tag": "p"}}
|
"type": {"name": "const char*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_check_cstring", "args": ["note"]}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,25 +3,6 @@
|
||||||
// Manual pointer size checking functions
|
// Manual pointer size checking functions
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
u64 orca_gles_check_cstring(IM3Runtime runtime, const char* ptr)
|
|
||||||
{
|
|
||||||
uint32_t memorySize = 0;
|
|
||||||
char* memory = (char*)m3_GetMemory(runtime, &memorySize, 0);
|
|
||||||
|
|
||||||
//NOTE: Here we are guaranteed that ptr is in [ memory ; memory + memorySize [
|
|
||||||
// hence (memory + memorySize) - ptr is representable by size_t and <= memorySize
|
|
||||||
size_t maxLen = (memory + memorySize) - ptr;
|
|
||||||
|
|
||||||
u64 len = strnlen(ptr, maxLen);
|
|
||||||
|
|
||||||
if(len == maxLen)
|
|
||||||
{
|
|
||||||
//NOTE: string overflows wasm memory, return a length that will trigger the bounds check
|
|
||||||
len = maxLen + 1;
|
|
||||||
}
|
|
||||||
return (len + 1); //include null-terminator
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 orca_gl_type_size(GLenum type)
|
u64 orca_gl_type_size(GLenum type)
|
||||||
{
|
{
|
||||||
u64 size = 8;
|
u64 size = 8;
|
||||||
|
@ -772,37 +753,37 @@ u64 orca_glGetUniformuiv_params_length(IM3Runtime runtime, GLuint program, GLint
|
||||||
|
|
||||||
u64 orca_glGetFragDataLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
u64 orca_glGetFragDataLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
||||||
{
|
{
|
||||||
return (orca_gles_check_cstring(runtime, name));
|
return (orca_check_cstring(runtime, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 orca_glGetUniformBlockIndex_uniformBlockName_length(IM3Runtime runtime, const GLchar* uniformBlockName)
|
u64 orca_glGetUniformBlockIndex_uniformBlockName_length(IM3Runtime runtime, const GLchar* uniformBlockName)
|
||||||
{
|
{
|
||||||
return (orca_gles_check_cstring(runtime, uniformBlockName));
|
return (orca_check_cstring(runtime, uniformBlockName));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 orca_glGetProgramResourceIndex_name_length(IM3Runtime runtime, const GLchar* name)
|
u64 orca_glGetProgramResourceIndex_name_length(IM3Runtime runtime, const GLchar* name)
|
||||||
{
|
{
|
||||||
return (orca_gles_check_cstring(runtime, name));
|
return (orca_check_cstring(runtime, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 orca_glGetProgramResourceLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
u64 orca_glGetProgramResourceLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
||||||
{
|
{
|
||||||
return (orca_gles_check_cstring(runtime, name));
|
return (orca_check_cstring(runtime, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 orca_glBindAttribLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
u64 orca_glBindAttribLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
||||||
{
|
{
|
||||||
return (orca_gles_check_cstring(runtime, name));
|
return (orca_check_cstring(runtime, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 orca_glGetAttribLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
u64 orca_glGetAttribLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
||||||
{
|
{
|
||||||
return (orca_gles_check_cstring(runtime, name));
|
return (orca_check_cstring(runtime, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 orca_glGetUniformLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
u64 orca_glGetUniformLocation_name_length(IM3Runtime runtime, const GLchar* name)
|
||||||
{
|
{
|
||||||
return (orca_gles_check_cstring(runtime, name));
|
return (orca_check_cstring(runtime, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
@ -967,7 +948,7 @@ const void* glGetUniformIndices_stub(IM3Runtime runtime, IM3ImportContext _ctx,
|
||||||
char* raw = ((char*)_mem + uniformNames[i]);
|
char* raw = ((char*)_mem + uniformNames[i]);
|
||||||
OC_ASSERT(raw >= (char*)_mem && (raw - (char*)_mem) < memorySize, "uniformName[%i] is out of bounds", i);
|
OC_ASSERT(raw >= (char*)_mem && (raw - (char*)_mem) < memorySize, "uniformName[%i] is out of bounds", i);
|
||||||
|
|
||||||
u64 len = orca_gles_check_cstring(runtime, raw);
|
u64 len = orca_check_cstring(runtime, raw);
|
||||||
|
|
||||||
OC_ASSERT(raw + len <= ((char*)_mem + memorySize), "uniformName[%i] overflows wasm memory", i);
|
OC_ASSERT(raw + len <= ((char*)_mem + memorySize), "uniformName[%i] overflows wasm memory", i);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
"cname": "oc_bridge_io_single_rect",
|
"cname": "oc_bridge_io_single_rect",
|
||||||
"ret": {"name": "oc_io_cmp", "tag": "S"},
|
"ret": {"name": "oc_io_cmp", "tag": "S"},
|
||||||
"args": [ {"name": "req",
|
"args": [ {"name": "req",
|
||||||
"type": {"name": "oc_io_req*", "tag": "p"}}]
|
"type": {"name": "oc_io_req*", "tag": "p"},
|
||||||
|
"len": {"components": 1}}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oc_file_open_with_request",
|
"name": "oc_file_open_with_request",
|
||||||
|
@ -31,7 +32,8 @@
|
||||||
{"name": "flags",
|
{"name": "flags",
|
||||||
"type": {"name": "oc_file_open_flags", "tag": "i"}},
|
"type": {"name": "oc_file_open_flags", "tag": "i"}},
|
||||||
{"name": "desc",
|
{"name": "desc",
|
||||||
"type": {"name": "oc_file_dialog_desc*", "cname": "oc_wasm_file_dialog_desc*", "tag": "p"}}
|
"type": {"name": "oc_file_dialog_desc*", "cname": "oc_wasm_file_dialog_desc*", "tag": "p"},
|
||||||
|
"len": {"components": 1}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
{"name": "region",
|
{"name": "region",
|
||||||
"type": {"name": "oc_rect", "tag": "S"}},
|
"type": {"name": "oc_rect", "tag": "S"}},
|
||||||
{"name": "pixels",
|
{"name": "pixels",
|
||||||
"type": {"name": "u8*", "tag": "p"}}]
|
"type": {"name": "u8*", "tag": "p"},
|
||||||
|
"len": {"proc": "orca_image_upload_region_rgba8_length", "args": ["region"]}}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oc_surface_get_size",
|
"name": "oc_surface_get_size",
|
||||||
|
@ -96,11 +97,13 @@
|
||||||
{"name": "primitiveCount",
|
{"name": "primitiveCount",
|
||||||
"type": {"name": "u32", "tag": "i"}},
|
"type": {"name": "u32", "tag": "i"}},
|
||||||
{"name": "primitives",
|
{"name": "primitives",
|
||||||
"type": {"name": "oc_primitive*", "tag": "p"}},
|
"type": {"name": "oc_primitive*", "tag": "p"},
|
||||||
|
"len": {"count": "primitiveCount"}},
|
||||||
{"name": "eltCount",
|
{"name": "eltCount",
|
||||||
"type": {"name": "u32", "tag": "i"}},
|
"type": {"name": "u32", "tag": "i"}},
|
||||||
{"name": "elements",
|
{"name": "elements",
|
||||||
"type": {"name": "oc_path_elt*", "tag": "p"}}]
|
"type": {"name": "oc_path_elt*", "tag": "p"},
|
||||||
|
"len": {"count": "eltCount"}}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oc_surface_canvas",
|
"name": "oc_surface_canvas",
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// image length checks
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
|
u64 orca_image_upload_region_rgba8_length(IM3Runtime runtime, oc_rect rect)
|
||||||
|
{
|
||||||
|
u64 pixelFormatWidth = sizeof(u8) * 4;
|
||||||
|
u64 len = rect.w * rect.h * pixelFormatWidth;
|
||||||
|
return len;
|
||||||
|
}
|
Loading…
Reference in New Issue