Skip to content

Commit

Permalink
deps: V8: cherry-pick 64-bit hash seed commits
Browse files Browse the repository at this point in the history
This serves as mitigation for the so-called HashWick vulnerability.

Original commit messages:

  commit d5686a74d56fbb6985b22663ddadd66eb7b91519
    Author: Yang Guo <yangguo@chromium.org>
    Date: Mon Jul 16 11:19:42 2018

    Extend hash seed to 64 bits

    R=bmeurer@chromium.org, ulan@chromium.org

    Bug: chromium:680662
    Change-Id: I5e1486ad2a42db2998d5485a0c4e711378678e6c
    Reviewed-on: https://chromium-review.googlesource.com/1136034
    Reviewed-by: Marja Hölttä <marja@chromium.org>
    Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
    Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
    Commit-Queue: Yang Guo <yangguo@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#54460}

  commit 3833fef57368c53c6170559ffa524c8c69f16ee5
    Author: Yang Guo <yangguo@chromium.org>
    Date: Thu Sep 20 11:43:13 2018

    Refactor integer hashing function names

    We now clearly differentiate between:
    - unseeded hash for 32-bit integers
    - unseeded hash for 64-bit integers
    - seeded hash for 32-bit integers
    - seeded hash for strings

    R=bmeurer@chromium.org

    Bug: chromium:680662
    Change-Id: I7459958c4158ee3501c962943dff8f33258bb5ce
    Reviewed-on: https://chromium-review.googlesource.com/1235973
    Commit-Queue: Yang Guo <yangguo@chromium.org>
    Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#56068}

  commit 95a979e02d7154e45b293261a6998c99d71fc238
    Author: Yang Guo <yangguo@chromium.org>
    Date: Thu Sep 20 14:34:48 2018

    Call into C++ to compute seeded integer hash

    R=bmeurer@chromium.org

    Bug: chromium:680662
    Change-Id: I8dace89d576dfcc5833fd539ce698a9ade1cb5a0
    Reviewed-on: https://chromium-review.googlesource.com/1235928
    Commit-Queue: Yang Guo <yangguo@chromium.org>
    Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#56091}

  commit 2c2af0022d5feb9e525a00a76cb15db9f3e38dba
    Author: Yang Guo <yangguo@chromium.org>
    Date: Thu Sep 27 16:37:57 2018

    Use 64-bit for seeded integer hashes

    R=petermarshall@chromium.org

    Bug: chromium:680662
    Change-Id: If48d1043dbe1e1bb695ec890c23e103a6cacf2d4
    Reviewed-on: https://chromium-review.googlesource.com/1244220
    Commit-Queue: Yang Guo <yangguo@chromium.org>
    Reviewed-by: Peter Marshall <petermarshall@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#56271}

Refs: #23259

PR-URL: #23274
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
hashseed authored and MylesBorins committed Oct 31, 2018
1 parent 104fbc6 commit 7ab253f
Show file tree
Hide file tree
Showing 36 changed files with 180 additions and 128 deletions.
2 changes: 1 addition & 1 deletion deps/v8/include/v8-version.h
Expand Up @@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 6
#define V8_MINOR_VERSION 2
#define V8_BUILD_NUMBER 414
#define V8_PATCH_LEVEL 68
#define V8_PATCH_LEVEL 69

// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Expand Down
10 changes: 10 additions & 0 deletions deps/v8/src/assembler.cc
Expand Up @@ -1432,6 +1432,16 @@ ExternalReference ExternalReference::check_object_type(Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(CheckObjectType)));
}

static uint32_t ComputeSeededIntegerHash(Isolate* isolate, uint32_t key) {
DisallowHeapAllocation no_gc;
return ComputeSeededHash(key, isolate->heap()->HashSeed());
}

ExternalReference ExternalReference::compute_integer_hash(Isolate* isolate) {
return ExternalReference(
Redirect(isolate, FUNCTION_ADDR(ComputeSeededIntegerHash)));
}

#ifdef V8_INTL_SUPPORT
ExternalReference ExternalReference::intl_convert_one_byte_to_lower(
Isolate* isolate) {
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/assembler.h
Expand Up @@ -979,7 +979,7 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference try_internalize_string_function(Isolate* isolate);

static ExternalReference check_object_type(Isolate* isolate);

static ExternalReference compute_integer_hash(Isolate* isolate);
#ifdef V8_INTL_SUPPORT
static ExternalReference intl_convert_one_byte_to_lower(Isolate* isolate);
static ExternalReference intl_to_latin1_lower_table(Isolate* isolate);
Expand Down
1 change: 0 additions & 1 deletion deps/v8/src/ast/ast-value-factory.cc
Expand Up @@ -202,7 +202,6 @@ bool AstValue::BooleanValue() const {
UNREACHABLE();
}


void AstValue::Internalize(Isolate* isolate) {
switch (type_) {
case STRING:
Expand Down
10 changes: 5 additions & 5 deletions deps/v8/src/ast/ast-value-factory.h
Expand Up @@ -361,7 +361,7 @@ class AstValue : public ZoneObject {

class AstStringConstants final {
public:
AstStringConstants(Isolate* isolate, uint32_t hash_seed)
AstStringConstants(Isolate* isolate, uint64_t hash_seed)
: zone_(isolate->allocator(), ZONE_NAME),
string_table_(AstRawString::Compare),
hash_seed_(hash_seed) {
Expand Down Expand Up @@ -391,15 +391,15 @@ class AstStringConstants final {
STRING_CONSTANTS(F)
#undef F

uint32_t hash_seed() const { return hash_seed_; }
uint64_t hash_seed() const { return hash_seed_; }
const base::CustomMatcherHashMap* string_table() const {
return &string_table_;
}

private:
Zone zone_;
base::CustomMatcherHashMap string_table_;
uint32_t hash_seed_;
uint64_t hash_seed_;

#define F(name, str) AstRawString* name##_string_;
STRING_CONSTANTS(F)
Expand All @@ -418,7 +418,7 @@ class AstStringConstants final {
class AstValueFactory {
public:
AstValueFactory(Zone* zone, const AstStringConstants* string_constants,
uint32_t hash_seed)
uint64_t hash_seed)
: string_table_(string_constants->string_table()),
values_(nullptr),
strings_(nullptr),
Expand Down Expand Up @@ -535,7 +535,7 @@ class AstValueFactory {

Zone* zone_;

uint32_t hash_seed_;
uint64_t hash_seed_;

#define F(name) AstValue* name##_;
OTHER_CONSTANTS(F)
Expand Down
11 changes: 5 additions & 6 deletions deps/v8/src/builtins/builtins-collections-gen.cc
Expand Up @@ -92,7 +92,7 @@ class CollectionsBuiltinsAssembler : public CodeStubAssembler {
Node* key_tagged, Variable* result,
Label* entry_found,
Label* not_found);
Node* ComputeIntegerHashForString(Node* context, Node* string_key);
Node* ComputeStringHash(Node* context, Node* string_key);
void SameValueZeroString(Node* context, Node* key_string, Node* candidate_key,
Label* if_same, Label* if_not_same);

Expand Down Expand Up @@ -515,8 +515,7 @@ void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForSmiKey(
Node* table, Node* smi_key, Variable* result, Label* entry_found,
Label* not_found) {
Node* const key_untagged = SmiUntag(smi_key);
Node* const hash =
ChangeInt32ToIntPtr(ComputeIntegerHash(key_untagged, Int32Constant(0)));
Node* const hash = ChangeInt32ToIntPtr(ComputeUnseededHash(key_untagged));
CSA_ASSERT(this, IntPtrGreaterThanOrEqual(hash, IntPtrConstant(0)));
result->Bind(hash);
FindOrderedHashTableEntry<CollectionType>(
Expand All @@ -531,7 +530,7 @@ template <typename CollectionType>
void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForStringKey(
Node* context, Node* table, Node* key_tagged, Variable* result,
Label* entry_found, Label* not_found) {
Node* const hash = ComputeIntegerHashForString(context, key_tagged);
Node* const hash = ComputeStringHash(context, key_tagged);
CSA_ASSERT(this, IntPtrGreaterThanOrEqual(hash, IntPtrConstant(0)));
result->Bind(hash);
FindOrderedHashTableEntry<CollectionType>(
Expand Down Expand Up @@ -573,8 +572,8 @@ void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForOtherKey(
result, entry_found, not_found);
}

Node* CollectionsBuiltinsAssembler::ComputeIntegerHashForString(
Node* context, Node* string_key) {
Node* CollectionsBuiltinsAssembler::ComputeStringHash(Node* context,
Node* string_key) {
VARIABLE(var_result, MachineType::PointerRepresentation());

Label hash_not_computed(this), done(this, &var_result);
Expand Down
44 changes: 27 additions & 17 deletions deps/v8/src/code-stub-assembler.cc
Expand Up @@ -200,10 +200,6 @@ HEAP_CONSTANT_LIST(HEAP_CONSTANT_ACCESSOR);
HEAP_CONSTANT_LIST(HEAP_CONSTANT_TEST);
#undef HEAP_CONSTANT_TEST

Node* CodeStubAssembler::HashSeed() {
return LoadAndUntagToWord32Root(Heap::kHashSeedRootIndex);
}

Node* CodeStubAssembler::StaleRegisterConstant() {
return LoadRoot(Heap::kStaleRegisterRootIndex);
}
Expand Down Expand Up @@ -5389,22 +5385,32 @@ template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>(
template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>(
Node*, Node*, Label*, Variable*, Label*, int, LookupMode);

Node* CodeStubAssembler::ComputeIntegerHash(Node* key) {
return ComputeIntegerHash(key, IntPtrConstant(kZeroHashSeed));
}

Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) {
// See v8::internal::ComputeIntegerHash()
Node* CodeStubAssembler::ComputeUnseededHash(Node* key) {
// See v8::internal::ComputeUnseededHash()
Node* hash = TruncateWordToWord32(key);
hash = Word32Xor(hash, seed);
hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)),
hash = Int32Add(Word32Xor(hash, Int32Constant(0xFFFFFFFF)),
Word32Shl(hash, Int32Constant(15)));
hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12)));
hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2)));
hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4)));
hash = Int32Mul(hash, Int32Constant(2057));
hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16)));
return Word32And(hash, Int32Constant(0x3fffffff));
return Word32And(hash, Int32Constant(0x3FFFFFFF));
}

Node* CodeStubAssembler::ComputeSeededHash(Node* key) {
Node* const function_addr =
ExternalConstant(ExternalReference::compute_integer_hash(isolate()));
Node* const isolate_ptr =
ExternalConstant(ExternalReference::isolate_address(isolate()));

MachineType type_ptr = MachineType::Pointer();
MachineType type_uint32 = MachineType::Uint32();

Node* const result =
CallCFunction2(type_uint32, type_ptr, type_uint32, function_addr,
isolate_ptr, TruncateWordToWord32(key));
return result;
}

template <typename Dictionary>
Expand All @@ -5420,10 +5426,14 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary,
Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary));
Node* mask = IntPtrSub(capacity, IntPtrConstant(1));

Node* int32_seed = std::is_same<Dictionary, SeededNumberDictionary>::value
? HashSeed()
: Int32Constant(kZeroHashSeed);
Node* hash = ChangeUint32ToWord(ComputeIntegerHash(intptr_index, int32_seed));
Node* hash;

if (std::is_same<Dictionary, SeededNumberDictionary>::value) {
hash = ChangeUint32ToWord(ComputeSeededHash(intptr_index));
} else {
hash = ChangeUint32ToWord(ComputeUnseededHash(intptr_index));
}

Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index);

// See Dictionary::FirstProbe().
Expand Down
5 changes: 2 additions & 3 deletions deps/v8/src/code-stub-assembler.h
Expand Up @@ -170,7 +170,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
HEAP_CONSTANT_LIST(HEAP_CONSTANT_TEST)
#undef HEAP_CONSTANT_TEST

Node* HashSeed();
Node* StaleRegisterConstant();

Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
Expand Down Expand Up @@ -1276,8 +1275,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
int inlined_probes = kInlinedDictionaryProbes,
LookupMode mode = kFindExisting);

Node* ComputeIntegerHash(Node* key);
Node* ComputeIntegerHash(Node* key, Node* seed);
Node* ComputeUnseededHash(Node* key);
Node* ComputeSeededHash(Node* key);

template <typename Dictionary>
void NumberDictionaryLookup(Node* dictionary, Node* intptr_index,
Expand Down
2 changes: 2 additions & 0 deletions deps/v8/src/external-reference-table.cc
Expand Up @@ -232,6 +232,8 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) {
"try_internalize_string_function");
Add(ExternalReference::check_object_type(isolate).address(),
"check_object_type");
Add(ExternalReference::compute_integer_hash(isolate).address(),
"ComputeSeededHash");
#ifdef V8_INTL_SUPPORT
Add(ExternalReference::intl_convert_one_byte_to_lower(isolate).address(),
"intl_convert_one_byte_to_lower");
Expand Down
7 changes: 4 additions & 3 deletions deps/v8/src/flag-definitions.h
Expand Up @@ -160,6 +160,7 @@ struct MaybeBoolFlag {
FLAG(MAYBE_BOOL, MaybeBoolFlag, nam, {false COMMA false}, cmt)
#define DEFINE_INT(nam, def, cmt) FLAG(INT, int, nam, def, cmt)
#define DEFINE_UINT(nam, def, cmt) FLAG(UINT, unsigned int, nam, def, cmt)
#define DEFINE_UINT64(nam, def, cmt) FLAG(UINT64, uint64_t, nam, def, cmt)
#define DEFINE_FLOAT(nam, def, cmt) FLAG(FLOAT, double, nam, def, cmt)
#define DEFINE_STRING(nam, def, cmt) FLAG(STRING, const char*, nam, def, cmt)
#define DEFINE_ARGS(nam, cmt) FLAG(ARGS, JSArguments, nam, {0 COMMA NULL}, cmt)
Expand Down Expand Up @@ -914,9 +915,9 @@ DEFINE_BOOL(randomize_hashes, true,
"(with snapshots this option cannot override the baked-in seed)")
DEFINE_BOOL(rehash_snapshot, true,
"rehash strings from the snapshot to override the baked-in seed")
DEFINE_INT(hash_seed, 0,
"Fixed seed to use to hash property keys (0 means random)"
"(with snapshots this option cannot override the baked-in seed)")
DEFINE_UINT64(hash_seed, 0,
"Fixed seed to use to hash property keys (0 means random)"
"(with snapshots this option cannot override the baked-in seed)")
DEFINE_INT(random_seed, 0,
"Default seed for initializing random generator "
"(0, the default, means to use system random).")
Expand Down
39 changes: 39 additions & 0 deletions deps/v8/src/flags.cc
Expand Up @@ -39,6 +39,7 @@ struct Flag {
TYPE_MAYBE_BOOL,
TYPE_INT,
TYPE_UINT,
TYPE_UINT64,
TYPE_FLOAT,
TYPE_STRING,
TYPE_ARGS
Expand Down Expand Up @@ -77,6 +78,11 @@ struct Flag {
return reinterpret_cast<unsigned int*>(valptr_);
}

uint64_t* uint64_variable() const {
DCHECK(type_ == TYPE_UINT64);
return reinterpret_cast<uint64_t*>(valptr_);
}

double* float_variable() const {
DCHECK(type_ == TYPE_FLOAT);
return reinterpret_cast<double*>(valptr_);
Expand Down Expand Up @@ -115,6 +121,11 @@ struct Flag {
return *reinterpret_cast<const unsigned int*>(defptr_);
}

uint64_t uint64_default() const {
DCHECK(type_ == TYPE_UINT64);
return *reinterpret_cast<const uint64_t*>(defptr_);
}

double float_default() const {
DCHECK(type_ == TYPE_FLOAT);
return *reinterpret_cast<const double*>(defptr_);
Expand All @@ -141,6 +152,8 @@ struct Flag {
return *int_variable() == int_default();
case TYPE_UINT:
return *uint_variable() == uint_default();
case TYPE_UINT64:
return *uint64_variable() == uint64_default();
case TYPE_FLOAT:
return *float_variable() == float_default();
case TYPE_STRING: {
Expand Down Expand Up @@ -171,6 +184,9 @@ struct Flag {
case TYPE_UINT:
*uint_variable() = uint_default();
break;
case TYPE_UINT64:
*uint64_variable() = uint64_default();
break;
case TYPE_FLOAT:
*float_variable() = float_default();
break;
Expand Down Expand Up @@ -201,6 +217,8 @@ static const char* Type2String(Flag::FlagType type) {
case Flag::TYPE_INT: return "int";
case Flag::TYPE_UINT:
return "uint";
case Flag::TYPE_UINT64:
return "uint64";
case Flag::TYPE_FLOAT: return "float";
case Flag::TYPE_STRING: return "string";
case Flag::TYPE_ARGS: return "arguments";
Expand All @@ -225,6 +243,9 @@ std::ostream& operator<<(std::ostream& os, const Flag& flag) { // NOLINT
case Flag::TYPE_UINT:
os << *flag.uint_variable();
break;
case Flag::TYPE_UINT64:
os << *flag.uint64_variable();
break;
case Flag::TYPE_FLOAT:
os << *flag.float_variable();
break;
Expand Down Expand Up @@ -443,6 +464,24 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
*flag->uint_variable() = static_cast<unsigned int>(val);
break;
}
case Flag::TYPE_UINT64: {
// We do not use strtoul because it accepts negative numbers.
int64_t val = static_cast<int64_t>(strtoll(value, &endp, 10));
if (val < 0 || val > std::numeric_limits<unsigned int>::max()) {
PrintF(stderr,
"Error: Value for flag %s of type %s is out of bounds "
"[0-%" PRIu64
"]\n"
"Try --help for options\n",
arg, Type2String(flag->type()),
static_cast<uint64_t>(
std::numeric_limits<unsigned int>::max()));
return_code = j;
break;
}
*flag->uint64_variable() = static_cast<uint64_t>(val);
break;
}
case Flag::TYPE_FLOAT:
*flag->float_variable() = strtod(value, &endp);
break;
Expand Down
3 changes: 2 additions & 1 deletion deps/v8/src/frames.cc
Expand Up @@ -2132,7 +2132,8 @@ InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
isolate_->counters()->pc_to_code()->Increment();
DCHECK(base::bits::IsPowerOfTwo(kInnerPointerToCodeCacheSize));
uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer));
uint32_t hash = ComputeUnseededHash(
ObjectAddressForHashing(reinterpret_cast<void*>(inner_pointer)));
uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
InnerPointerToCodeCacheEntry* entry = cache(index);
if (entry->inner_pointer == inner_pointer) {
Expand Down
6 changes: 3 additions & 3 deletions deps/v8/src/heap/heap-inl.h
Expand Up @@ -614,13 +614,13 @@ Oddball* Heap::ToBoolean(bool condition) {
return condition ? true_value() : false_value();
}

uint32_t Heap::HashSeed() {
uint32_t seed = static_cast<uint32_t>(hash_seed()->value());
uint64_t Heap::HashSeed() {
uint64_t seed;
hash_seed()->copy_out(0, reinterpret_cast<byte*>(&seed), kInt64Size);
DCHECK(FLAG_randomize_hashes || seed == 0);
return seed;
}


int Heap::NextScriptId() {
int last_id = last_script_id()->value();
if (last_id == Smi::kMaxValue) {
Expand Down

0 comments on commit 7ab253f

Please sign in to comment.