Skip to content

Commit 889c978

Browse files
committed
Bounds-checking for array attributes.
1 parent fc95a31 commit 889c978

File tree

5 files changed

+44
-9
lines changed

5 files changed

+44
-9
lines changed

tests/webidl/output.txt

+6-4
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ unsigned short int: 65535
6969
return unsigned long -1
7070
unsigned long int: 4294967295
7171
void * 3
72-
array[0] == 0
73-
array[7] == 7
74-
array[0] == 42
75-
array[7] == 43
72+
int_array[0] == 0
73+
int_array[7] == 7
74+
int_array[0] == 42
75+
int_array[7] == 43
76+
idx -1: Array index -1 out of bounds: [0,8)
77+
idx 8: Array index 8 out of bounds: [0,8)
7678
struct_array[0].attr1 == 0
7779
struct_array[0].attr2 == 0
7880
struct_array[7].attr1 == 7

tests/webidl/post.js

+21-4
Original file line numberDiff line numberDiff line change
@@ -154,18 +154,35 @@ TheModule.print('void * ' + voidPointerUser.GetVoidPointer());
154154
// Array tests
155155

156156
var arrayClass = new TheModule.ArrayClass();
157-
TheModule.print('array[0] == ' + arrayClass.get_int_array(0));
158-
TheModule.print('array[7] == ' + arrayClass.get_int_array(7));
157+
TheModule.print('int_array[0] == ' + arrayClass.get_int_array(0));
158+
TheModule.print('int_array[7] == ' + arrayClass.get_int_array(7));
159159
arrayClass.set_int_array(0, 42);
160160
arrayClass.set_int_array(7, 43);
161-
TheModule.print('array[0] == ' + arrayClass.get_int_array(0));
162-
TheModule.print('array[7] == ' + arrayClass.get_int_array(7));
161+
TheModule.print('int_array[0] == ' + arrayClass.get_int_array(0));
162+
TheModule.print('int_array[7] == ' + arrayClass.get_int_array(7));
163+
164+
try {
165+
arrayClass.set_int_array(-1, struct);
166+
} catch (e) {
167+
TheModule.print('idx -1: ' + e);
168+
}
169+
170+
try {
171+
arrayClass.set_int_array(8, struct);
172+
} catch (e) {
173+
TheModule.print('idx 8: ' + e);
174+
}
163175

164176
TheModule.print('struct_array[0].attr1 == ' + arrayClass.get_struct_array(0).get_attr1());
165177
TheModule.print('struct_array[0].attr2 == ' + arrayClass.get_struct_array(0).get_attr2());
166178
TheModule.print('struct_array[7].attr1 == ' + arrayClass.get_struct_array(7).get_attr1());
167179
TheModule.print('struct_array[7].attr2 == ' + arrayClass.get_struct_array(7).get_attr2());
168180

181+
// Verify that bounds checking is *not* enabled when not asked for.
182+
// This actually causes an illegal memory access, but as it's only a read, and the return
183+
// value is not used, it shouldn't cause any problems in practice.
184+
arrayClass.get_struct_array(8);
185+
169186
var struct = new TheModule.StructInArray(13, 17);
170187
arrayClass.set_struct_array(0, struct);
171188
struct = new TheModule.StructInArray(14, 18);

tests/webidl/test.idl

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ interface StructInArray {
118118

119119
interface ArrayClass {
120120
void ArrayClass();
121-
attribute long[] int_array;
121+
[BoundsChecked] attribute long[] int_array;
122122
[Value] attribute StructInArray[] struct_array;
123123
attribute StructInArray[] struct_ptr_array;
124124
};

third_party/WebIDL.py

+1
Original file line numberDiff line numberDiff line change
@@ -2855,6 +2855,7 @@ def handleExtendedAttribute(self, attr):
28552855
identifier == "AvailableIn" or
28562856
identifier == "Const" or
28572857
identifier == "Value" or
2858+
identifier == "BoundsChecked" or
28582859
identifier == "NewObject"):
28592860
# Known attributes that we don't need to do anything with here
28602861
pass

tools/webidl_binder.py

+15
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ def emit_constructor(name):
132132
133133
''']
134134

135+
mid_c += ['''
136+
// Not using size_t for array indices as the values used by the javascript code are signed.
137+
void array_bounds_check(const int array_size, const int array_idx) {
138+
if (array_idx < 0 || array_idx >= array_size) {
139+
EM_ASM_INT({
140+
throw 'Array index ' + $0 + ' out of bounds: [0,' + $1 + ')';
141+
}, array_idx, array_size);
142+
}
143+
}
144+
''']
145+
135146
C_FLOATS = ['float', 'double']
136147

137148
def type_to_c(t, non_pointing=False):
@@ -388,6 +399,10 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer, copy,
388399
Dummy({ 'type': m.type })] }
389400
get_call_content = take_addr_if_nonpointer(m) + 'self->' + attr + '[arg0]'
390401
set_call_content = 'self->' + attr + '[arg0] = ' + deref_if_nonpointer(m) + 'arg1'
402+
if m.getExtendedAttribute('BoundsChecked'):
403+
bounds_check = "array_bounds_check(sizeof(self->%s) / sizeof(self->%s[0]), arg0)" % (attr, attr)
404+
get_call_content = "(%s, %s)" % (bounds_check, get_call_content)
405+
set_call_content = "(%s, %s)" % (bounds_check, set_call_content)
391406
else:
392407
get_sigs = { 0: [] }
393408
set_sigs = { 1: [Dummy({ 'type': m.type })] }

0 commit comments

Comments
 (0)