1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-26 12:10:59 +01:00

* Take the position of self-references into account when computing

content hashes.  This is to prevent a rewrite of
 
    ...HASH...HASH...

  and

    ...HASH...0000...

  (where HASH is the randomly generated prefix) from hashing to the
  same value.  This would happen because they would both resolve to
  ...0000...0000...  Exploiting this into a security hole is left as
  an exercise to the reader ;-)
This commit is contained in:
Eelco Dolstra 2005-05-21 01:22:36 +00:00
parent 049e74ccf6
commit f06a9429cf

View file

@ -35,14 +35,12 @@ bool PathHash::isNull() const
bool PathHash::operator ==(const PathHash & hash2) const bool PathHash::operator ==(const PathHash & hash2) const
{ {
debug("foo");
return rep == hash2.rep; return rep == hash2.rep;
} }
bool PathHash::operator <(const PathHash & hash2) const bool PathHash::operator <(const PathHash & hash2) const
{ {
debug("bar");
return rep < hash2.rep; return rep < hash2.rep;
} }
@ -71,7 +69,8 @@ struct CopySource : RestoreSource
}; };
string rewriteHashes(string s, const HashRewrites & rewrites) static string rewriteHashes(string s, const HashRewrites & rewrites,
vector<int> & positions)
{ {
for (HashRewrites::const_iterator i = rewrites.begin(); for (HashRewrites::const_iterator i = rewrites.begin();
i != rewrites.end(); ++i) i != rewrites.end(); ++i)
@ -83,6 +82,7 @@ string rewriteHashes(string s, const HashRewrites & rewrites)
unsigned int j = 0; unsigned int j = 0;
while ((j = s.find(from, j)) != string::npos) { while ((j = s.find(from, j)) != string::npos) {
debug(format("rewriting @ %1%") % j); debug(format("rewriting @ %1%") % j);
positions.push_back(j);
s.replace(j, to.size(), to); s.replace(j, to.size(), to);
} }
} }
@ -93,14 +93,26 @@ string rewriteHashes(string s, const HashRewrites & rewrites)
PathHash hashModulo(string s, const PathHash & modulus) PathHash hashModulo(string s, const PathHash & modulus)
{ {
vector<int> positions;
if (!modulus.isNull()) { if (!modulus.isNull()) {
/* Zero out occurences of `modulus'. */ /* Zero out occurences of `modulus'. */
HashRewrites rewrites; HashRewrites rewrites;
rewrites[modulus] = PathHash(); /* = null hash */ rewrites[modulus] = PathHash(); /* = null hash */
s = rewriteHashes(s, rewrites); s = rewriteHashes(s, rewrites, positions);
} }
return PathHash(hashString(htSHA256, s)); string positionPrefix;
for (vector<int>::iterator i = positions.begin();
i != positions.end(); ++i)
positionPrefix += (format("|%1%") % *i).str();
positionPrefix += "||";
debug(format("positions %1%") % positionPrefix);
return PathHash(hashString(htSHA256, positionPrefix + s));
} }
@ -118,7 +130,8 @@ Path addToStore(const Path & srcPath, const PathHash & selfHash)
if (!selfHash.isNull()) { if (!selfHash.isNull()) {
HashRewrites rewrites; HashRewrites rewrites;
rewrites[selfHash] = newHash; rewrites[selfHash] = newHash;
sink.s = rewriteHashes(sink.s, rewrites); vector<int> positions;
sink.s = rewriteHashes(sink.s, rewrites, positions);
PathHash newHash2 = hashModulo(sink.s, newHash); PathHash newHash2 = hashModulo(sink.s, newHash);
assert(newHash2 == newHash); assert(newHash2 == newHash);
debug(format("newHash2 %1%") % newHash2.toString()); debug(format("newHash2 %1%") % newHash2.toString());
@ -137,7 +150,7 @@ int main(int argc, char * * argv)
{ {
verbosity = (Verbosity) ((int) 10); verbosity = (Verbosity) ((int) 10);
Path p = addToStore("./bar", PathHash(parseHash32(htSHA256, "8myr6ajc52b5sky7iplgz8jv703ljc0q"))); Path p = addToStore("./foo", PathHash(parseHash32(htSHA256, "8myr6ajc52b5sky7iplgz8jv703ljc0q")));
cout << p << endl; cout << p << endl;