Skip to content

Commit

Permalink
deps: cherry-pick 64-bit hash seed commits from V8
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: #23260
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
  • Loading branch information
hashseed authored and targos committed Oct 7, 2018
1 parent 77de1be commit f08373f
Show file tree
Hide file tree
Showing 40 changed files with 172 additions and 140 deletions.
4 changes: 2 additions & 2 deletions common.gypi
Expand Up @@ -25,15 +25,15 @@
'uv_library%': 'static_library',

'clang%': 0,

'openssl_fips%': '',

# Default to -O0 for debug builds.
'v8_optimized_debug%': 0,

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.32',
'v8_embedder_string': '-node.33',

# Enable disassembler for `--print-code` v8 options
'v8_enable_disassembler': 1,
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/ast/ast-value-factory.cc
Expand Up @@ -182,7 +182,7 @@ std::forward_list<const AstRawString*> AstConsString::ToRawStrings() const {
return result;
}

AstStringConstants::AstStringConstants(Isolate* isolate, uint32_t hash_seed)
AstStringConstants::AstStringConstants(Isolate* isolate, uint64_t hash_seed)
: zone_(isolate->allocator(), ZONE_NAME),
string_table_(AstRawString::Compare),
hash_seed_(hash_seed) {
Expand Down
10 changes: 5 additions & 5 deletions deps/v8/src/ast/ast-value-factory.h
Expand Up @@ -240,22 +240,22 @@ class AstBigInt {

class AstStringConstants final {
public:
AstStringConstants(Isolate* isolate, uint32_t hash_seed);
AstStringConstants(Isolate* isolate, uint64_t hash_seed);

#define F(name, str) \
const AstRawString* name##_string() const { return name##_string_; }
AST_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_;
AST_STRING_CONSTANTS(F)
Expand All @@ -267,7 +267,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()),
strings_(nullptr),
strings_end_(&strings_),
Expand Down Expand Up @@ -354,7 +354,7 @@ class AstValueFactory {

Zone* zone_;

uint32_t hash_seed_;
uint64_t hash_seed_;
};
} // namespace internal
} // namespace v8
Expand Down
11 changes: 5 additions & 6 deletions deps/v8/src/builtins/builtins-collections-gen.cc
Expand Up @@ -684,7 +684,7 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler {
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 @@ -828,8 +828,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 @@ -844,7 +843,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 @@ -902,8 +901,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
32 changes: 18 additions & 14 deletions deps/v8/src/code-stub-assembler.cc
Expand Up @@ -230,10 +230,6 @@ HEAP_CONSTANT_LIST(HEAP_CONSTANT_ACCESSOR);
HEAP_CONSTANT_LIST(HEAP_CONSTANT_TEST);
#undef HEAP_CONSTANT_TEST

TNode<Int32T> CodeStubAssembler::HashSeed() {
return LoadAndUntagToWord32Root(Heap::kHashSeedRootIndex);
}

Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) {
if (mode == SMI_PARAMETERS) {
return SmiConstant(value);
Expand Down Expand Up @@ -7094,14 +7090,9 @@ template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>(
TNode<GlobalDictionary>, TNode<Name>, Label*, TVariable<IntPtrT>*, 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 = TruncateIntPtrToInt32(key);
hash = Word32Xor(hash, seed);
hash = Int32Add(Word32Xor(hash, Int32Constant(0xFFFFFFFF)),
Word32Shl(hash, Int32Constant(15)));
hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12)));
Expand All @@ -7112,6 +7103,21 @@ Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) {
return Word32And(hash, Int32Constant(0x3FFFFFFF));
}

Node* CodeStubAssembler::ComputeSeededHash(Node* key) {
Node* const function_addr =
ExternalConstant(ExternalReference::compute_integer_hash());
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, TruncateIntPtrToInt32(key));
return result;
}

void CodeStubAssembler::NumberDictionaryLookup(
TNode<NumberDictionary> dictionary, TNode<IntPtrT> intptr_index,
Label* if_found, TVariable<IntPtrT>* var_entry, Label* if_not_found) {
Expand All @@ -7122,9 +7128,7 @@ void CodeStubAssembler::NumberDictionaryLookup(
TNode<IntPtrT> capacity = SmiUntag(GetCapacity<NumberDictionary>(dictionary));
TNode<WordT> mask = IntPtrSub(capacity, IntPtrConstant(1));

TNode<Int32T> int32_seed = HashSeed();
TNode<WordT> hash =
ChangeUint32ToWord(ComputeIntegerHash(intptr_index, int32_seed));
TNode<WordT> hash = ChangeUint32ToWord(ComputeSeededHash(intptr_index));
Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index);

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

TNode<Int32T> HashSeed();

Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
TNode<BoolT> BoolConstant(bool value) {
return value ? Int32TrueConstant() : Int32FalseConstant();
Expand Down Expand Up @@ -1883,8 +1881,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);

void NumberDictionaryLookup(TNode<NumberDictionary> dictionary,
TNode<IntPtrT> intptr_index, Label* if_found,
Expand Down
6 changes: 3 additions & 3 deletions deps/v8/src/compiler/effect-control-linearizer.cc
Expand Up @@ -4583,8 +4583,8 @@ Node* EffectControlLinearizer::LowerFindOrderedHashMapEntry(Node* node) {
}
}

Node* EffectControlLinearizer::ComputeIntegerHash(Node* value) {
// See v8::internal::ComputeIntegerHash()
Node* EffectControlLinearizer::ComputeUnseededHash(Node* value) {
// See v8::internal::ComputeUnseededHash()
value = __ Int32Add(__ Word32Xor(value, __ Int32Constant(0xFFFFFFFF)),
__ Word32Shl(value, __ Int32Constant(15)));
value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(12)));
Expand All @@ -4602,7 +4602,7 @@ Node* EffectControlLinearizer::LowerFindOrderedHashMapEntryForInt32Key(
Node* key = NodeProperties::GetValueInput(node, 1);

// Compute the integer hash code.
Node* hash = ChangeUint32ToUintPtr(ComputeIntegerHash(key));
Node* hash = ChangeUint32ToUintPtr(ComputeUnseededHash(key));

Node* number_of_buckets = ChangeSmiToIntPtr(__ LoadField(
AccessBuilder::ForOrderedHashTableBaseNumberOfBuckets(), table));
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/compiler/effect-control-linearizer.h
Expand Up @@ -178,7 +178,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* frame_state);
Node* BuildFloat64RoundDown(Node* value);
Node* BuildFloat64RoundTruncate(Node* input);
Node* ComputeIntegerHash(Node* value);
Node* ComputeUnseededHash(Node* value);
Node* LowerStringComparison(Callable const& callable, Node* node);
Node* IsElementsKindGreaterThan(Node* kind, ElementsKind reference_kind);

Expand Down
9 changes: 9 additions & 0 deletions deps/v8/src/external-reference.cc
Expand Up @@ -778,6 +778,15 @@ ExternalReference ExternalReference::jsreceiver_create_identity_hash(
return ExternalReference(Redirect(FUNCTION_ADDR(f)));
}

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

ExternalReference ExternalReference::compute_integer_hash() {
return ExternalReference(Redirect(FUNCTION_ADDR(ComputeSeededIntegerHash)));
}

ExternalReference
ExternalReference::copy_fast_number_jsarray_elements_to_typed_array() {
return ExternalReference(
Expand Down
1 change: 1 addition & 0 deletions deps/v8/src/external-reference.h
Expand Up @@ -81,6 +81,7 @@ class StatsCounter;
V(address_of_uint32_bias, "uint32_bias") \
V(bytecode_size_table_address, "Bytecodes::bytecode_size_table_address") \
V(check_object_type, "check_object_type") \
V(compute_integer_hash, "ComputeSeededHash") \
V(compute_output_frames_function, "Deoptimizer::ComputeOutputFrames()") \
V(copy_fast_number_jsarray_elements_to_typed_array, \
"copy_fast_number_jsarray_elements_to_typed_array") \
Expand Down
7 changes: 4 additions & 3 deletions deps/v8/src/flag-definitions.h
Expand Up @@ -162,6 +162,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_SIZE_T(nam, def, cmt) FLAG(SIZE_T, size_t, nam, def, cmt)
#define DEFINE_STRING(nam, def, cmt) FLAG(STRING, const char*, nam, def, cmt)
Expand Down Expand Up @@ -1019,9 +1020,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
27 changes: 27 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_SIZE_T,
TYPE_STRING,
Expand Down Expand Up @@ -78,6 +79,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 @@ -121,6 +127,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 Down Expand Up @@ -152,6 +163,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_SIZE_T:
Expand Down Expand Up @@ -184,6 +197,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 @@ -217,6 +233,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_SIZE_T:
return "size_t";
Expand All @@ -243,6 +261,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 @@ -464,6 +485,12 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
return_code = j;
}
break;
case Flag::TYPE_UINT64:
if (!TryParseUnsigned(flag, arg, value, &endp,
flag->uint64_variable())) {
return_code = j;
}
break;
case Flag::TYPE_FLOAT:
*flag->float_variable() = strtod(value, &endp);
break;
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/frames.cc
Expand Up @@ -2146,7 +2146,7 @@ InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
isolate_->counters()->pc_to_code()->Increment();
DCHECK(base::bits::IsPowerOfTwo(kInnerPointerToCodeCacheSize));
uint32_t hash = ComputeIntegerHash(
uint32_t hash = ComputeUnseededHash(
ObjectAddressForHashing(reinterpret_cast<void*>(inner_pointer)));
uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
InnerPointerToCodeCacheEntry* entry = cache(index);
Expand Down
6 changes: 3 additions & 3 deletions deps/v8/src/heap/heap-inl.h
Expand Up @@ -529,13 +529,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) last_id = v8::UnboundScript::kNoScriptId;
Expand Down

0 comments on commit f08373f

Please sign in to comment.