Skip to content

Commit a6d3c61

Browse files
mgreterxzyfer
authored andcommitted
Fix hash collisions with complex values
Uses a copy of `hash_combine` from boost!
1 parent f45e14b commit a6d3c61

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

ast.hpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@
5353
namespace Sass {
5454
using namespace std;
5555

56+
// from boost (functional/hash):
57+
// http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html
58+
// Boost Software License - Version 1.0
59+
// http://www.boost.org/users/license.html
60+
template <typename T>
61+
void hash_combine (std::size_t& seed, const T& val)
62+
{
63+
seed ^= std::hash<T>()(val) + 0x9e3779b9
64+
+ (seed<<6) + (seed>>2);
65+
}
66+
5667
//////////////////////////////////////////////////////////
5768
// Abstract base class for all abstract syntax tree nodes.
5869
//////////////////////////////////////////////////////////
@@ -137,7 +148,7 @@ namespace std {
137148
{
138149
bool operator()( Sass::Expression* lhs, Sass::Expression* rhs) const
139150
{
140-
return *lhs == *rhs;
151+
return lhs->hash() == rhs->hash();
141152
}
142153
};
143154
}
@@ -768,7 +779,7 @@ namespace Sass {
768779
hash_ = std::hash<string>()(separator() == COMMA ? "comma" : "space");
769780

770781
for (size_t i = 0, L = length(); i < L; ++i)
771-
hash_ ^= (elements()[i])->hash();
782+
hash_combine(hash_, (elements()[i])->hash());
772783

773784
return hash_;
774785
}
@@ -819,8 +830,10 @@ namespace Sass {
819830
{
820831
if (hash_ > 0) return hash_;
821832

822-
for (auto key : keys())
823-
hash_ ^= key->hash() ^ at(key)->hash();
833+
for (auto key : keys()) {
834+
hash_combine(hash_, key->hash());
835+
hash_combine(hash_, at(key)->hash());
836+
}
824837

825838
return hash_;
826839
}
@@ -1085,7 +1098,7 @@ namespace Sass {
10851098

10861099
hash_ = std::hash<string>()(name());
10871100
for (auto argument : arguments()->elements())
1088-
hash_ ^= argument->hash();
1101+
hash_combine(hash_, argument->hash());
10891102

10901103
return hash_;
10911104
}
@@ -1347,7 +1360,7 @@ namespace Sass {
13471360
if (hash_ > 0) return hash_;
13481361

13491362
for (auto string : elements())
1350-
hash_ ^= string->hash();
1363+
hash_combine(hash_, string->hash());
13511364

13521365
return hash_;
13531366
}

debugger.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
465465
" [delayed: " << expression->is_delayed() << "] " <<
466466
" [interpolant: " << expression->is_interpolant() << "] " <<
467467
" [arglist: " << expression->is_arglist() << "] " <<
468+
" [hash: " << expression->hash() << "] " <<
468469
endl;
469470
for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
470471
} else if (dynamic_cast<Content*>(node)) {

0 commit comments

Comments
 (0)