Consolidate code that verifies array index bounds
This commit is contained in:
parent
ae9ae4dc77
commit
a5bd3264c1
|
@ -29,13 +29,22 @@ size_t ObjectArray::size() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Row ObjectArray::get(std::size_t row_ndx) {
|
Row ObjectArray::get(std::size_t row_ndx) {
|
||||||
if (row_ndx >= link_view->size()) {
|
verify_valid_row(row_ndx);
|
||||||
throw std::range_error(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." +
|
|
||||||
std::to_string(link_view->size()) + ".");
|
|
||||||
}
|
|
||||||
return link_view->get(row_ndx);
|
return link_view->get(row_ndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectArray::set(std::size_t row_ndx, std::size_t target_row_ndx) {
|
||||||
|
verify_valid_row(row_ndx);
|
||||||
|
link_view->set(row_ndx, target_row_ndx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectArray::verify_valid_row(std::size_t row_ndx) {
|
||||||
|
size_t size = link_view->size();
|
||||||
|
if (row_ndx >= size) {
|
||||||
|
throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectArray::verify_attached() {
|
void ObjectArray::verify_attached() {
|
||||||
if (!link_view->is_attached()) {
|
if (!link_view->is_attached()) {
|
||||||
throw std::runtime_error("Tableview is not attached");
|
throw std::runtime_error("Tableview is not attached");
|
||||||
|
@ -57,6 +66,14 @@ static inline ObjectArray * RJSVerifiedMutableArray(JSObjectRef object) {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t RJSVerifiedPositiveIndex(std::string indexStr) {
|
||||||
|
long index = std::stol(indexStr);
|
||||||
|
if (index < 0) {
|
||||||
|
throw std::out_of_range(std::string("Index ") + indexStr + " cannot be less than zero.");
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
|
JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
|
||||||
try {
|
try {
|
||||||
// index subscripting
|
// index subscripting
|
||||||
|
@ -68,7 +85,7 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr
|
||||||
return JSValueMakeNumber(ctx, size);
|
return JSValueMakeNumber(ctx, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(std::stol(indexStr))));
|
return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(RJSVerifiedPositiveIndex(indexStr))));
|
||||||
}
|
}
|
||||||
catch (std::invalid_argument &exp) {
|
catch (std::invalid_argument &exp) {
|
||||||
// for stol failure this could be another property that is handled externally, so ignore
|
// for stol failure this could be another property that is handled externally, so ignore
|
||||||
|
@ -85,18 +102,12 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr
|
||||||
bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) {
|
bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) {
|
||||||
try {
|
try {
|
||||||
ObjectArray *array = RJSVerifiedMutableArray(object);
|
ObjectArray *array = RJSVerifiedMutableArray(object);
|
||||||
size_t size = array->size();
|
|
||||||
std::string indexStr = RJSStringForJSString(propertyName);
|
std::string indexStr = RJSStringForJSString(propertyName);
|
||||||
if (indexStr == "length") {
|
if (indexStr == "length") {
|
||||||
throw std::runtime_error("The 'length' property is readonly.");
|
throw std::runtime_error("The 'length' property is readonly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = std::stol(indexStr);
|
array->set(RJSVerifiedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(value), array->object_schema.name, false));
|
||||||
if (index >= size) {
|
|
||||||
throw std::out_of_range("Cannot set list item beyond its bounds.");
|
|
||||||
}
|
|
||||||
|
|
||||||
array->link_view->set(index, RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(value), array->object_schema.name, false));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (std::invalid_argument &exp) {
|
catch (std::invalid_argument &exp) {
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace realm {
|
||||||
|
|
||||||
size_t size();
|
size_t size();
|
||||||
Row get(std::size_t row_ndx);
|
Row get(std::size_t row_ndx);
|
||||||
|
void set(std::size_t row_ndx, std::size_t target_row_ndx);
|
||||||
|
void verify_valid_row(std::size_t row_ndx);
|
||||||
void verify_attached();
|
void verify_attached();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue