7 Stimmen

Fehler im Algorithmus zur Erzeugung von Hash-Schlüsseln im Firefox-Cache

Es gibt ein Fehler in Firefox (auch in den neuen Betas und in Minenfeld-Releases), die das Zwischenspeichern bestimmter Dateien aufgrund des Algorithmus zur Erstellung eines Schlüssels in ihrem Cache-Hash verhindert. Hier ist ein Link zum Quellcode der Funktion .

Ich möchte sicherstellen, dass alle Dateien meiner Website im Cache gespeichert werden können. Ich verstehe jedoch nicht, warum ihre Hashing-Funktion keine eindeutigen Schlüssel für bestimmte URLs erzeugt. Ich hoffe, jemand kann dies beschreiben mal Funktion in Psuedo-Code oder Java.

Es wäre gut, ein Dienstprogramm für Entwickler zu erstellen, um eindeutige URLs sicherzustellen, bis dieser Fehler behoben ist.


EDIT : Es gab einige sehr hilfreiche Antworten, aber ich brauche mehr schrittweise Hilfe, um ein Dienstprogramm zu erstellen, das diese Cache-Verwechslungen aufspürt. Es wäre toll, einen Java-Code zu bekommen, der die von Firefox erzeugten Schlüssel reproduzieren kann. Daher die Eröffnung eines Kopfgeldes auf diese Frage.


EDIT 2: Hier ist eine teilweise funktionierende Java-Portierung (geschrieben mit Verarbeitung ). Beachten Sie die Tests am unteren Rand; die ersten drei funktionieren wie erwartet, die anderen jedoch nicht. Ich vermute, dass es etwas mit signierten/unsignierten Ints zu tun hat. Vorschläge?

//
// the bad collision function
// http://mxr.mozilla.org/mozilla/source/netwerk/cache/src/nsDiskCacheDevice.cpp#240
//

//248 PLDHashNumber
//249 nsDiskCache::Hash(const char * key)
//250 {
//251     PLDHashNumber h = 0;
//252     for (const PRUint8* s = (PRUint8*) key; *s != '\0'; ++s)
//253         h = PR_ROTATE_LEFT32(h, 4) ^ *s;
//254     return (h == 0 ? ULONG_MAX : h);
//255 }

//
//  a java port...
//

String getHash( String url )
{

//get the char array for the url string
char[] cs = getCharArray( url );

int h = 0;

//for (const PRUint8* s = (PRUint8*) key; *s != '\0'; ++s)
for ( int i=0; i < cs.length; i++ )
{  h = PR_ROTATE_LEFT32(h, 4) ^ cs[i];
}

//looks like the examples above return something in hex.
//if we get matching ints, that is ok by me.
//but for fun, lets try to hex the return vals?
String hexVal = hex( h );
return hexVal;
}

char[] getCharArray( String s )
{
  char[] cs = new char[s.length()];
  for (int i=0; i<s.length(); i++)
  { 
    char c = s.charAt(i);
    cs[i] = c;
  } 

  return cs;
}

//
// how to PR_ROTATE_LEFT32
//

//110 /*
//111 ** Macros for rotate left and right. The argument 'a' must be an unsigned
//112 ** 32-bit integer type such as PRUint32.
//113 **
//114 ** There is no rotate operation in the C Language, so the construct
//115 ** (a << 4) | (a >> 28) is frequently used instead. Most compilers convert
//116 ** this to a rotate instruction, but MSVC doesn't without a little help.
//117 ** To get MSVC to generate a rotate instruction, we have to use the _rotl
//118 ** or _rotr intrinsic and use a pragma to make it inline.
//119 **
//120 ** Note: MSVC in VS2005 will do an inline rotate instruction on the above
//121 ** construct.
//122 */
//...
//128 #define PR_ROTATE_LEFT32(a, bits) _rotl(a, bits)

//return an int (32 bit).  what do we do with the 'bits' parameter?  ignore?
int PR_ROTATE_LEFT32( int a, int bits )
{    return (a << 4) | (a >> (32-bits)); 
}

//
// examples of some colliding hashes
// https://bugzilla.mozilla.org/show_bug.cgi?id=290032#c5
//

//$ ./hashit "ABA/xxx.aba"
//8ffac222
//$ ./hashit "XyZ/xxx.xYz"
//8ffac222
//$ ./hashit "CSS/xxx.css"
//8ffac222
//$ ./hashit "JPG/xxx.jpg"
//8ffac222

//$ ./hashit modules_newsfeeds/MenuBar/MenuBar.css
//15c23729
//$ ./hashit modules_newsfeeds/ListBar/ListBar.css
//15c23729

//$ ./hashit modules_newsfeeds/MenuBar/MenuBar.js
//a15c23e5
//$ ./hashit modules_newsfeeds/ListBar/ListBar.js
//a15c23e5

//
// our attempt at porting this algorithm to java...
//

void setup( )
{

String a = "ABA/xxx.aba";
String b = "CSS/xxx.css";
String c = "CSS/xxx.css";
String d = "JPG/xxx.jpg";

println( getHash(a) ); //yes 8ffac222
println( getHash(b) ); //yes 8ffac222
println( getHash(c) ); //yes 8ffac222
println( getHash(d) ); //no [??] FFFFFF98, not 8ffac222

println( "-----" );

String e = "modules_newsfeeds/MenuBar/MenuBar.css";
String f = "modules_newsfeeds/ListBar/ListBar.css";

println( getHash(e) ); //no [??] FFFFFF8C, not 15c23729
println( getHash(f) ); //no [??] FFFFFF8C, not 15c23729

println( "-----" );

String g = "modules_newsfeeds/MenuBar/MenuBar.js";
String h = "modules_newsfeeds/ListBar/ListBar.js";

println( getHash(g) ); //yes [??] FFFFFF8C, not a15c23e5
println( getHash(h) ); //yes [??] FFFFFF8C, not a15c23e5

}

0voto

MSalters Punkte 166675

Sie irren sich offensichtlich, was den wirklichen Fehler angeht. Sicher, es gibt Hash-Kollisionen aufgrund der unglaublich schlechten Wahl des Hash-Algorithmus. Aber selbst hash(x)=1 würde nicht die beschriebenen Probleme verursachen. Es würde lediglich eine O(1)-Lookup in eine O(N)-Verknüpfte-Liste-Suche durch den ersten Bucket verwandeln.

Das eigentliche Problem ist, dass Firefox nicht mit Hash-Kollisionen umgehen kann. Er benötigt daher einen perfekten Hash für alle URLs. "Alle URLs" ist leider eine Menge, die außerhalb Ihrer Kontrolle liegt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X