Consolidate code that verifies array index bounds

This commit is contained in:
Scott Kyle 2015-10-12 15:02:44 -07:00
parent ae9ae4dc77
commit a5bd3264c1
2 changed files with 25 additions and 12 deletions

View File

@ -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) {

View File

@ -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();
}; };
} }