Skip to content

Commit a79a008

Browse files
committed
src: fix String::Length for Node.js v12.3.0
Type of String::Length changed from SMI to int32. This commit changes String::Length to use the new type. String::Length now returns a CheckedType, and places calling String::Length will check the type using .Check instead of Error::Fail, making the code more resilient in case the String length can't be loaded properly. PR-URL: #302 Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent 2964af5 commit a79a008

File tree

5 files changed

+62
-16
lines changed

5 files changed

+62
-16
lines changed

src/llv8-constants.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,12 @@ void String::Load() {
299299
kExternalStringTag = LoadConstant("ExternalStringTag");
300300
kThinStringTag = LoadConstant("ThinStringTag");
301301

302+
kLengthIsSmi = true;
302303
kLengthOffset = LoadConstant("class_String__length__SMI");
304+
if (kLengthOffset == -1) {
305+
kLengthIsSmi = false;
306+
kLengthOffset = LoadConstant("class_String__length__int32_t");
307+
}
303308
}
304309

305310

src/llv8-constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ class String : public Module {
266266
int64_t kThinStringTag;
267267

268268
int64_t kLengthOffset;
269+
bool kLengthIsSmi;
269270

270271
protected:
271272
void Load();

src/llv8-inl.h

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ inline int32_t LLV8::LoadValue<int32_t>(int64_t addr, Error& err) {
1717
return LoadUnsigned(addr, 4, err);
1818
}
1919

20+
template <>
21+
inline CheckedType<int32_t> LLV8::LoadValue<CheckedType<int32_t>>(
22+
int64_t addr) {
23+
return LoadUnsigned<int32_t>(addr, 4);
24+
}
25+
2026
template <class T>
2127
inline T LLV8::LoadValue(int64_t addr, Error& err) {
2228
int64_t ptr;
@@ -363,7 +369,23 @@ inline int64_t String::Encoding(Error& err) {
363369
return type & v8()->string()->kEncodingMask;
364370
}
365371

366-
ACCESSOR(String, Length, string()->kLengthOffset, Smi)
372+
inline CheckedType<int32_t> String::Length(Error& err) {
373+
RETURN_IF_INVALID((*this), CheckedType<int32_t>());
374+
375+
if (v8()->string()->kLengthIsSmi) {
376+
Smi len = LoadFieldValue<Smi>(v8()->string()->kLengthOffset, err);
377+
RETURN_IF_INVALID(len, CheckedType<int32_t>());
378+
379+
return CheckedType<int32_t>(len.GetValue());
380+
}
381+
382+
CheckedType<int32_t> len = v8()->LoadValue<CheckedType<int32_t>>(
383+
LeaField(v8()->string()->kLengthOffset));
384+
RETURN_IF_INVALID(len, CheckedType<int32_t>());
385+
386+
return len;
387+
}
388+
367389

368390
ACCESSOR(Script, Name, script()->kNameOffset, String)
369391
ACCESSOR(Script, LineOffset, script()->kLineOffsetOffset, Smi)
@@ -610,16 +632,16 @@ inline int64_t FixedTypedArrayBase::GetExternal(Error& err) {
610632

611633
inline std::string OneByteString::ToString(Error& err) {
612634
int64_t chars = LeaField(v8()->one_byte_string()->kCharsOffset);
613-
Smi len = Length(err);
614-
if (err.Fail()) return std::string();
615-
return v8()->LoadString(chars, len.GetValue(), err);
635+
CheckedType<int32_t> len = Length(err);
636+
RETURN_IF_INVALID(len, std::string());
637+
return v8()->LoadString(chars, *len, err);
616638
}
617639

618640
inline std::string TwoByteString::ToString(Error& err) {
619641
int64_t chars = LeaField(v8()->two_byte_string()->kCharsOffset);
620-
Smi len = Length(err);
621-
if (err.Fail()) return std::string();
622-
return v8()->LoadTwoByteString(chars, len.GetValue(), err);
642+
CheckedType<int32_t> len = Length(err);
643+
RETURN_IF_INVALID(len, std::string());
644+
return v8()->LoadTwoByteString(chars, *len, err);
623645
}
624646

625647
inline std::string ConsString::ToString(Error& err) {
@@ -653,24 +675,23 @@ inline std::string SlicedString::ToString(Error& err) {
653675
Smi offset = Offset(err);
654676
if (err.Fail()) return std::string();
655677

656-
Smi length = Length(err);
657-
if (err.Fail()) return std::string();
678+
CheckedType<int32_t> length = Length(err);
679+
RETURN_IF_INVALID(length, std::string());
658680

659681
std::string tmp = parent.ToString(err);
660682
if (err.Fail()) return std::string();
661683

662684
int64_t off = offset.GetValue();
663-
int64_t len = length.GetValue();
664685
int64_t tmp_size = tmp.size();
665-
if (off > tmp_size || len > tmp_size) {
686+
if (off > tmp_size || *length > tmp_size) {
666687
err = Error::Failure("Failed to display sliced string 0x%016" PRIx64
667-
" (offset = 0x%016" PRIx64 ", length = 0x%016" PRIx64
668-
") from parent string 0x%016" PRIx64
688+
" (offset = 0x%016" PRIx64
689+
", length = %d) from parent string 0x%016" PRIx64
669690
" (length = 0x%016" PRIx64 ")",
670-
raw(), off, len, parent.raw(), tmp_size);
691+
raw(), off, *length, parent.raw(), tmp_size);
671692
return std::string(err.GetMessage());
672693
}
673-
return tmp.substr(offset.GetValue(), length.GetValue());
694+
return tmp.substr(offset.GetValue(), *length);
674695
}
675696

676697
inline std::string ThinString::ToString(Error& err) {

src/llv8.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,20 @@ int64_t LLV8::LoadPtr(int64_t addr, Error& err) {
8080
return value;
8181
}
8282

83+
template <class T>
84+
CheckedType<T> LLV8::LoadUnsigned(int64_t addr, uint32_t byte_size) {
85+
SBError sberr;
86+
int64_t value = process_.ReadUnsignedFromMemory(static_cast<addr_t>(addr),
87+
byte_size, sberr);
88+
89+
if (sberr.Fail()) {
90+
PRINT_DEBUG("Failed to load unsigned from v8 memory. Reason: %s",
91+
sberr.GetCString());
92+
return CheckedType<T>();
93+
}
94+
95+
return CheckedType<T>(value);
96+
}
8397

8498
int64_t LLV8::LoadUnsigned(int64_t addr, uint32_t byte_size, Error& err) {
8599
SBError sberr;

src/llv8.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class String : public HeapObject {
163163

164164
inline int64_t Encoding(Error& err);
165165
inline CheckedType<int64_t> Representation(Error& err);
166-
inline Smi Length(Error& err);
166+
inline CheckedType<int32_t> Length(Error& err);
167167

168168
std::string ToString(Error& err);
169169

@@ -605,8 +605,13 @@ class LLV8 {
605605
template <class T>
606606
inline T LoadValue(int64_t addr, Error& err);
607607

608+
template <class T>
609+
inline T LoadValue(int64_t addr);
610+
608611
int64_t LoadConstant(const char* name);
609612
int64_t LoadPtr(int64_t addr, Error& err);
613+
template <class T>
614+
CheckedType<T> LoadUnsigned(int64_t addr, uint32_t byte_size);
610615
int64_t LoadUnsigned(int64_t addr, uint32_t byte_size, Error& err);
611616
double LoadDouble(int64_t addr, Error& err);
612617
std::string LoadBytes(int64_t addr, int64_t length, Error& err);

0 commit comments

Comments
 (0)