Skip to content

Commit 960b997

Browse files
authored
Allocate buffers when the buffer pointer is requested (#4812)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent 3ad76f9 commit 960b997

File tree

4 files changed

+109
-44
lines changed

4 files changed

+109
-44
lines changed

jerry-core/api/jerry.c

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6072,6 +6072,29 @@ jerry_create_shared_arraybuffer_external (const jerry_length_t size, /**< size o
60726072
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
60736073
} /* jerry_create_shared_arraybuffer_external */
60746074

6075+
#if JERRY_BUILTIN_TYPEDARRAY
6076+
6077+
/**
6078+
* Allocate a backing store for an array buffer, ignores allocation fails.
6079+
*
6080+
* @return true on success,
6081+
* false otherwise
6082+
*/
6083+
static bool
6084+
jerry_arraybuffer_allocate_buffer_no_throw (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */
6085+
{
6086+
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED));
6087+
6088+
if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED)
6089+
{
6090+
return false;
6091+
}
6092+
6093+
return ecma_arraybuffer_allocate_buffer (arraybuffer_p) != NULL;
6094+
} /* jerry_arraybuffer_allocate_buffer_no_throw */
6095+
6096+
#endif /* JERRY_BUILTIN_TYPEDARRAY */
6097+
60756098
/**
60766099
* Copy bytes into the ArrayBuffer or SharedArrayBuffer from a buffer.
60776100
*
@@ -6094,15 +6117,15 @@ jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer or S
60946117
return 0;
60956118
}
60966119

6097-
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
6120+
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value);
60986121

6099-
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
6122+
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)
6123+
&& !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p))
61006124
{
6101-
jerry_release_value (jcontext_take_exception ());
61026125
return 0;
61036126
}
61046127

6105-
jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
6128+
jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p);
61066129

61076130
if (offset >= length)
61086131
{
@@ -6113,9 +6136,9 @@ jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer or S
61136136

61146137
if (copy_count > 0)
61156138
{
6116-
lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
6139+
lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p);
61176140

6118-
memcpy ((void *) (mem_buffer_p + offset), (void *) buf_p, copy_count);
6141+
memcpy ((void *) (buffer_p + offset), (void *) buf_p, copy_count);
61196142
}
61206143

61216144
return copy_count;
@@ -6150,15 +6173,15 @@ jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer or SharedArr
61506173
return 0;
61516174
}
61526175

6153-
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
6176+
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value);
61546177

6155-
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
6178+
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)
6179+
&& !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p))
61566180
{
6157-
jerry_release_value (jcontext_take_exception ());
61586181
return 0;
61596182
}
61606183

6161-
jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
6184+
jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p);
61626185

61636186
if (offset >= length)
61646187
{
@@ -6169,9 +6192,9 @@ jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer or SharedArr
61696192

61706193
if (copy_count > 0)
61716194
{
6172-
lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
6195+
lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p);
61736196

6174-
memcpy ((void *) buf_p, (void *) (mem_buffer_p + offset), copy_count);
6197+
memcpy ((void *) buf_p, (void *) (buffer_p + offset), copy_count);
61756198
}
61766199

61776200
return copy_count;
@@ -6200,8 +6223,8 @@ jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer o
62006223
#if JERRY_BUILTIN_TYPEDARRAY
62016224
if (ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value))
62026225
{
6203-
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
6204-
return ecma_arraybuffer_get_length (buffer_p);
6226+
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value);
6227+
return ecma_arraybuffer_get_length (arraybuffer_p);
62056228
}
62066229
#else /* !JERRY_BUILTIN_TYPEDARRAY */
62076230
JERRY_UNUSED (value);
@@ -6232,14 +6255,15 @@ jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buff
62326255
return NULL;
62336256
}
62346257

6235-
ecma_object_t *buffer_p = ecma_get_object_from_value (array_buffer);
6258+
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (array_buffer);
62366259

6237-
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (buffer_p) & ECMA_ARRAYBUFFER_ALLOCATED))
6260+
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)
6261+
&& !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p))
62386262
{
62396263
return NULL;
62406264
}
62416265

6242-
return (uint8_t *) ecma_arraybuffer_get_buffer (buffer_p);
6266+
return (uint8_t *) ecma_arraybuffer_get_buffer (arraybuffer_p);
62436267
#else /* !JERRY_BUILTIN_TYPEDARRAY */
62446268
JERRY_UNUSED (array_buffer);
62456269
#endif /* JERRY_BUILTIN_TYPEDARRAY */

jerry-core/ecma/operations/ecma-arraybuffer-object.c

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -128,26 +128,21 @@ ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */
128128
/**
129129
* Allocate a backing store for an array buffer.
130130
*
131-
* @return ECMA_VALUE_UNDEFINED on success,
132-
* ECMA_VALUE_ERROR otherwise
131+
* @return buffer pointer on success,
132+
* NULL otherwise
133133
*/
134-
ecma_value_t
135-
ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p) /**< ArrayBuffer object */
134+
uint8_t *
135+
ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */
136136
{
137-
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED));
138-
139-
if (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED)
140-
{
141-
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
142-
}
143-
144-
JERRY_ASSERT (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER);
137+
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED));
138+
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED));
139+
JERRY_ASSERT (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_HAS_POINTER);
145140

146-
ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) object_p;
141+
ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) arraybuffer_p;
147142
uint32_t arraybuffer_length = extended_object_p->u.cls.u3.length;
148-
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
143+
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p;
149144
jerry_arraybuffer_allocate_t arraybuffer_allocate_callback = JERRY_CONTEXT (arraybuffer_allocate_callback);
150-
void *buffer_p;
145+
uint8_t *buffer_p;
151146

152147
if (arraybuffer_allocate_callback != NULL)
153148
{
@@ -167,33 +162,59 @@ ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p) /**< ArrayBuffer obje
167162
}
168163
else
169164
{
170-
buffer_p = jmem_heap_alloc_block_null_on_error (arraybuffer_length);
165+
buffer_p = (uint8_t *) jmem_heap_alloc_block_null_on_error (arraybuffer_length);
171166
}
172167

173168
if (buffer_p == NULL)
174169
{
175170
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_DETACHED;
176-
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for ArrayBuffer"));
171+
return NULL;
177172
}
178173

179174
arraybuffer_pointer_p->buffer_p = buffer_p;
180175
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED;
181176

182177
memset (buffer_p, 0, arraybuffer_length);
183-
return ECMA_VALUE_UNDEFINED;
178+
return buffer_p;
184179
} /* ecma_arraybuffer_allocate_buffer */
185180

181+
/**
182+
* Allocate a backing store for an array buffer, throws an error if the allocation fails.
183+
*
184+
* @return ECMA_VALUE_UNDEFINED on success,
185+
* ECMA_VALUE_ERROR otherwise
186+
*/
187+
ecma_value_t
188+
ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p)
189+
{
190+
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED));
191+
192+
if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED)
193+
{
194+
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
195+
}
196+
197+
uint8_t *buffer_p = ecma_arraybuffer_allocate_buffer (arraybuffer_p);
198+
199+
if (buffer_p == NULL)
200+
{
201+
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for ArrayBuffer"));
202+
}
203+
204+
return ECMA_VALUE_UNDEFINED;
205+
} /* ecma_arraybuffer_allocate_buffer_throw */
206+
186207
/**
187208
* Release the backing store allocated by an array buffer.
188209
*/
189210
void
190-
ecma_arraybuffer_release_buffer (ecma_object_t *object_p) /**< ArrayBuffer object */
211+
ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */
191212
{
192-
JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
193-
|| ecma_object_is_shared_arraybuffer (object_p));
213+
JERRY_ASSERT (ecma_object_class_is (arraybuffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
214+
|| ecma_object_is_shared_arraybuffer (arraybuffer_p));
194215

195216
jerry_arraybuffer_free_t free_callback = JERRY_CONTEXT (arraybuffer_free_callback);
196-
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
217+
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p;
197218
uint32_t arraybuffer_length = arraybuffer_pointer_p->extended_object.u.cls.u3.length;
198219

199220
if (free_callback == NULL)

jerry-core/ecma/operations/ecma-arraybuffer-object.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
*/
3939
#define ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR(arraybuffer_p) \
4040
(JERRY_UNLIKELY (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)) \
41-
&& ecma_arraybuffer_allocate_buffer (arraybuffer_p) == ECMA_VALUE_ERROR)
41+
&& ecma_arraybuffer_allocate_buffer_throw (arraybuffer_p) == ECMA_VALUE_ERROR)
4242

4343
ecma_value_t
4444
ecma_op_create_arraybuffer_object (const ecma_value_t *, uint32_t);
@@ -52,10 +52,12 @@ ecma_object_t *
5252
ecma_arraybuffer_create_object_with_buffer (uint8_t type, uint32_t length);
5353
ecma_object_t *
5454
ecma_arraybuffer_new_object (uint32_t length);
55+
uint8_t *
56+
ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p);
5557
ecma_value_t
56-
ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p);
58+
ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p);
5759
void
58-
ecma_arraybuffer_release_buffer (ecma_object_t *object_p);
60+
ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p);
5961
uint8_t * JERRY_ATTR_PURE
6062
ecma_arraybuffer_get_buffer (ecma_object_t *obj_p);
6163
uint32_t JERRY_ATTR_PURE

tests/unit-core/test-arraybuffer.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,8 @@ main (void)
376376

377377
uint8_t *const data = jerry_get_arraybuffer_pointer (buffer);
378378

379+
TEST_ASSERT (data != NULL);
380+
379381
/* test memory read */
380382
for (int i = 0; i < 20; i++)
381383
{
@@ -472,15 +474,31 @@ main (void)
472474
}
473475

474476
/* Test ArrayBuffer created in ECMAScript */
477+
for (int i = 0; i < 3; i++)
475478
{
476479
const jerry_char_t source[] = TEST_STRING_LITERAL ("new ArrayBuffer(64)");
477480
jerry_value_t arraybuffer = jerry_eval (source, sizeof (source) - 1, JERRY_PARSE_NO_OPTS);
478481
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
479482
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
480483
TEST_ASSERT (!jerry_arraybuffer_has_buffer (arraybuffer));
481484

482-
uint8_t buf[2] = { 2, 3 };
483-
TEST_ASSERT (jerry_arraybuffer_write (arraybuffer, 63, buf, 2) == 1);
485+
if (i == 0)
486+
{
487+
uint8_t buf[2] = { 2, 3 };
488+
TEST_ASSERT (jerry_arraybuffer_write (arraybuffer, 63, buf, 2) == 1);
489+
}
490+
else if (i == 1)
491+
{
492+
uint8_t buf[2] = { 1, 1 };
493+
TEST_ASSERT (jerry_arraybuffer_read (arraybuffer, 63, buf, 2) == 1);
494+
TEST_ASSERT (buf[0] == 0 && buf[1] == 1);
495+
}
496+
else
497+
{
498+
uint8_t *buffer_p = jerry_get_arraybuffer_pointer (arraybuffer);
499+
TEST_ASSERT (buffer_p != NULL);
500+
}
501+
484502
TEST_ASSERT (jerry_arraybuffer_has_buffer (arraybuffer));
485503

486504
jerry_release_value (arraybuffer);

0 commit comments

Comments
 (0)