Xxhash: Verwenden Sie nach kostenlos mit Streaming XXH3 Seed + copyState

Erstellt am 19. Mai 2020  ·  7Kommentare  ·  Quelle: Cyan4973/xxHash

Gutschrift an @koraa.

Derzeit weist dieser Code eine Verwendung nach der kostenlosen Ausgabe auf:

void bugged(void)
{
    XXH3_state_t *a = XXH3_createState();
    XXH3_state_t *b = XXH3_createState();
    XXH3_64bits_reset_withSeed(a, 0x1234567890abcdefull);
    XXH3_copyState(b, a);
    XXH3_freeState(a);
    // Bug
    XXH3_64bits_update(b, "BUGGED", strlen("BUGGED"));
    XXH3_freeState(b);
}

Dies liegt daran, dass a->secret auf a->customSecret zeigt und XXH3_copyState diesen Zeiger nicht aktualisiert (es ist buchstäblich nur memcpy ), also b->secret zeigt auf a->customSecret .

Nachdem a freigegeben wurde, ist b->secret jetzt ein ungültiger Zeiger.

xxh3 use after free

Hilfreichster Kommentar

Ich denke, die beste Option ist der NULL Zeiger.

Es gibt bereits 5 Filialen am Anfang von XXH3_update . Es schadet nicht, noch einen zu machen (zumal es nur benötigt wird, wenn der Puffer gefüllt ist)

Alle 7 Kommentare

Siehe Diskussion in #361.

Es gibt einige Optionen.

Die erste und einfachste Option, die keine Änderungen am Verhalten hat, ist diese:

XXH_PUBLIC_API XXH_errorcode
XXH3_copyState(XXH3_state_t* dst, const XXH3_state_t* src)
{
    XXH_memcpy(dst, src, sizeof(XXH3_state_t));
    if (src->secret == &src->customSecret[0]) {
        dst->secret = &dst->customSecret[0];
    }
    return XXH_OK;
}

Dies ist jedoch ein wenig hackig.

Die zweite Möglichkeit besteht darin, eines der reservierten Felder zu verwenden, um festzustellen, um welche Art von Zustand es sich handelt, und dies zu verwenden, anstatt Rohzeiger zu vergleichen.

Während wir dies tun, könnten wir eine Fehlerprüfung hinzufügen, um eine Vermischung von 64-Bit- und 128-Bit-Zuständen zu verhindern. Dies würde das Verhalten ändern, aber diese Verwendung war sowieso nicht beabsichtigt und kann als UB angesehen werden.

Die dritte Option besteht darin, einen NULL Zeiger für den Seed-Modus zu verwenden, und wenn er NULL ist, verwenden Sie customSecret anstelle von secret , aber dies würde eine Verzweigung hinzufügen. Es gibt jedoch bereits genug Overhead von der Zustandsverwaltung, dass es wahrscheinlich einen nicht wahrnehmbaren Unterschied machen würde.

Die letzte Option besteht darin, malloc() eine Kopie des geheimen Zeigers zu erstellen.

Dadurch ändert sich die ABI, da sie nicht mehr vollständig im Stack-Speicher ausgeführt werden kann. Es wird auch für kSecret hochgradig redundant sein.

Es ermöglicht jedoch, benutzerdefinierte Geheimnisse nach reset_withSeed() ungültig zu machen und die Größe des Zustands zu verkleinern.

Ups, versehentlich den falschen Knopf gedrückt :facepalm:

Ich denke, es gibt eine vierte Option: Immer den Entropiepool in die Struktur kopieren; Dies würde jedoch dazu führen, dass der Pool die Größe des Standardgeheimnisses hat. Das mag zwar nett sein und die Grundlage für die Offline-Optimierung der Entropiepool-Generierung bilden.

uint64_t XXH3_64bits_withEntropyPool(XXH3_state_t &pool, uint8_t data, size_t size);

Die Implementierung würde den XXH3-Zustand mit den gegebenen Daten "erweitern"; den Hash sofort zurückgeben, ohne den Zustand zu ändern ...

BEARBEITEN Dies würde die Beweglichkeit erhalten; welches IMO ein großer Segen für die Benutzerfreundlichkeit ist und für eine Rostintegration sehr geschätzt würde.

uint64_t XXH3_64bits_withEntropyPool(XXH3_state_t &pool, uint8_t data, size_t size);
error: expected ')'
...XXH3_64bits_withEntropyPool(XXH3_state_t &pool, uint8_t data,...
                                            ^
note: to match this '('
uint64_t XXH3_64bits_withEntropyPool(XXH3_state_t &pool, uint8_t...
                                    ^
1 error generated.

Was ist das? Ich weiß nicht, was du da vorhast... :smirk:

Beweglichkeit wäre ein nettes Feature und wäre mit einem Geheimnis mit fester Größe einfach.

Eigentlich wäre alles einfacher (und schneller) mit einem Secret mit fester Größe, aber wir wollen die API nicht durcheinander bringen.

Ich denke, die beste Option ist der NULL Zeiger.

Es gibt bereits 5 Filialen am Anfang von XXH3_update . Es schadet nicht, noch einen zu machen (zumal es nur benötigt wird, wenn der Puffer gefüllt ist)

Es ist auch zu beachten, dass x86_64 und i686 dies ohne Verzweigung tun können:

        lea     tmp, [state + offsetof (state::customSecret)]
        test    secret, secret
        cmove   secret, tmp

Dies ist auch branchenlos auf ARM

        cmp     secret, #0
        it      eq
        addeq   secret, state, offsetof(state::customSecret)

und auf AArch64:

        add     tmp, state, offsetof(state::customSecret)
        cmp     secret, #0
        csel    secret, tmp, secret, eq
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

jtoivainen picture jtoivainen  ·  4Kommentare

witedragen picture witedragen  ·  3Kommentare

shuffle2 picture shuffle2  ·  6Kommentare

make-github-pseudonymous-again picture make-github-pseudonymous-again  ·  3Kommentare

t-mat picture t-mat  ·  3Kommentare