|
38 | 38 | #include "src/objects/elements-kind.h" |
39 | 39 | #include "src/objects/feedback-vector.h" |
40 | 40 | #include "src/objects/heap-number.h" |
| 41 | +#include "src/objects/property-details.h" |
41 | 42 | #include "src/objects/string.h" |
42 | 43 |
|
43 | 44 | namespace v8 { |
@@ -4235,25 +4236,59 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore( |
4235 | 4236 | // for intermediate states of chains of property additions. That makes |
4236 | 4237 | // it unclear what the best approach is here. |
4237 | 4238 | DCHECK_EQ(map.UnusedPropertyFields(), 0); |
4238 | | - int length = map.NextFreePropertyIndex() - map.GetInObjectProperties(); |
| 4239 | + int in_object_length = map.GetInObjectProperties(); |
| 4240 | + int length = map.NextFreePropertyIndex() - in_object_length; |
4239 | 4241 | // Under normal circumstances, NextFreePropertyIndex() will always be larger |
4240 | 4242 | // than GetInObjectProperties(). However, an attacker able to corrupt heap |
4241 | 4243 | // memory can break this invariant, in which case we'll get confused here, |
4242 | 4244 | // potentially causing a sandbox violation. This CHECK defends against that. |
4243 | 4245 | SBXCHECK_GE(length, 0); |
4244 | 4246 | int new_length = length + JSObject::kFieldsAdded; |
| 4247 | + |
| 4248 | + // Find the descriptor index corresponding to the first out-of-object |
| 4249 | + // property. |
| 4250 | + DescriptorArrayRef descs = map.instance_descriptors(broker()); |
| 4251 | + InternalIndex first_out_of_object_descriptor(in_object_length); |
| 4252 | + InternalIndex number_of_descriptors(descs.object()->number_of_descriptors()); |
| 4253 | + for (InternalIndex i(in_object_length); i < number_of_descriptors; ++i) { |
| 4254 | + PropertyDetails details = descs.GetPropertyDetails(i); |
| 4255 | + // Skip over non-field properties. |
| 4256 | + if (details.location() != PropertyLocation::kField) { |
| 4257 | + continue; |
| 4258 | + } |
| 4259 | + // Skip over in-object fields. |
| 4260 | + // TODO(leszeks): We could make this smarter, like a binary search. |
| 4261 | + if (details.field_index() < in_object_length) { |
| 4262 | + continue; |
| 4263 | + } |
| 4264 | + first_out_of_object_descriptor = i; |
| 4265 | + break; |
| 4266 | + } |
| 4267 | + |
4245 | 4268 | // Collect the field values from the {properties}. |
4246 | | - ZoneVector<Node*> values(zone()); |
| 4269 | + ZoneVector<std::pair<Node*, Representation>> values(zone()); |
4247 | 4270 | values.reserve(new_length); |
4248 | | - for (int i = 0; i < length; ++i) { |
| 4271 | + |
| 4272 | + // Walk the property descriptors alongside the property values, to make |
| 4273 | + // sure to get and store them with the right machine type. |
| 4274 | + InternalIndex descriptor = first_out_of_object_descriptor; |
| 4275 | + for (int i = 0; i < length; ++i, ++descriptor) { |
| 4276 | + PropertyDetails details = descs.GetPropertyDetails(descriptor); |
| 4277 | + while (details.location() != PropertyLocation::kField) { |
| 4278 | + ++descriptor; |
| 4279 | + details = descs.GetPropertyDetails(descriptor); |
| 4280 | + } |
| 4281 | + DCHECK_EQ(i, details.field_index() - in_object_length); |
4249 | 4282 | Node* value = effect = graph()->NewNode( |
4250 | | - simplified()->LoadField(AccessBuilder::ForFixedArraySlot(i)), |
| 4283 | + simplified()->LoadField( |
| 4284 | + AccessBuilder::ForPropertyArraySlot(i, details.representation())), |
4251 | 4285 | properties, effect, control); |
4252 | | - values.push_back(value); |
| 4286 | + values.push_back({value, details.representation()}); |
4253 | 4287 | } |
4254 | 4288 | // Initialize the new fields to undefined. |
4255 | 4289 | for (int i = 0; i < JSObject::kFieldsAdded; ++i) { |
4256 | | - values.push_back(jsgraph()->UndefinedConstant()); |
| 4290 | + values.push_back( |
| 4291 | + {jsgraph()->UndefinedConstant(), Representation::Tagged()}); |
4257 | 4292 | } |
4258 | 4293 |
|
4259 | 4294 | // Compute new length and hash. |
@@ -4291,7 +4326,8 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore( |
4291 | 4326 | a.Store(AccessBuilder::ForMap(), jsgraph()->PropertyArrayMapConstant()); |
4292 | 4327 | a.Store(AccessBuilder::ForPropertyArrayLengthAndHash(), new_length_and_hash); |
4293 | 4328 | for (int i = 0; i < new_length; ++i) { |
4294 | | - a.Store(AccessBuilder::ForFixedArraySlot(i), values[i]); |
| 4329 | + a.Store(AccessBuilder::ForPropertyArraySlot(i, values[i].second), |
| 4330 | + values[i].first); |
4295 | 4331 | } |
4296 | 4332 | return a.Finish(); |
4297 | 4333 | } |
|
0 commit comments