Forum: Mikrocontroller und Digitale Elektronik zlib: adler32 Prüfsummer rechnet falsch


von Rangi J. (rangi)


Lesenswert?

Hallo Forum,
ich habe PNG (libpng) auf meinem STM32 zum laufen gebracht. Darin 
enthalten ist ja die zlib und diese bringt die adler32() Prüfsumme mit. 
Funktioniert soweit prima, bis auf das die Prüfsumme nicht mit der Summe 
des png-Bildes übereinstimmt.
Wenn ich die Überprüfung abschalte (ganz am Ende) wird der Bildinhalt 
korrekt ausgegeben, keine Fehler.
Hat jemand sowas schonmal gemacht? Gibts da irgendwas zu beachten?
1
#define BASE 65521      /* largest prime smaller than 65536 */
2
#define NMAX 5552
3
#define MOD(a) a %= BASE
4
#define MOD28(a) a %= BASE
5
6
#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
7
#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
8
#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
9
#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
10
#define DO16(buf)   DO8(buf,0); DO8(buf,8);
11
12
u32 adler32(u32 adler, const u8 *buf, u32 len)
13
{
14
    u32 sum2;
15
    u32 n;
16
17
    /* split Adler-32 into component sums */
18
    sum2 = (adler >> 16) & 0xffff;
19
    adler &= 0xffff;
20
21
    /* in case user likes doing a byte at a time, keep it fast */
22
    if (len == 1) {
23
        adler += buf[0];
24
        if (adler >= BASE)
25
            adler -= BASE;
26
        sum2 += adler;
27
        if (sum2 >= BASE)
28
            sum2 -= BASE;
29
        return adler | (sum2 << 16);
30
    }
31
32
    /* initial Adler-32 value (deferred check for len == 1 speed) */
33
    if (buf == NULL)
34
        return 1L;
35
36
    /* in case short lengths are provided, keep it somewhat fast */
37
    if (len < 16) {
38
        while (len--) {
39
            adler += *buf++;
40
            sum2 += adler;
41
        }
42
        if (adler >= BASE)
43
            adler -= BASE;
44
        MOD28(sum2);            /* only added so many BASE's */
45
        return adler | (sum2 << 16);
46
    }
47
48
    /* do length NMAX blocks -- requires just one modulo operation */
49
    while (len >= NMAX) {
50
        len -= NMAX;
51
        n = NMAX / 16;          /* NMAX is divisible by 16 */
52
        do {
53
            DO16(buf);          /* 16 sums unrolled */
54
            buf += 16;
55
        } while (--n);
56
        MOD(adler);
57
        MOD(sum2);
58
    }
59
60
    /* do remaining bytes (less than NMAX, still just one modulo) */
61
    if (len) {                  /* avoid modulos if none remaining */
62
        while (len >= 16) {
63
            len -= 16;
64
            DO16(buf);
65
            buf += 16;
66
        }
67
        while (len--) {
68
            adler += *buf++;
69
            sum2 += adler;
70
        }
71
        MOD(adler);
72
        MOD(sum2);
73
    }
74
75
    /* return recombined sums */
76
    return adler | (sum2 << 16);
77
}

Initialisieren muss man den ja scheinbar nicht, denn im case "HEAD" 
steht:
1
            Tracev((stderr, "inflate:   zlib header ok\n"));
2
            strm->adler = state->check = adler32(0L, NULL, 0);

von Dr. Sommer (Gast)


Lesenswert?

Auf PC und Controller mit den gleichen Eingabedaten aufrufen, bei jedem 
Schritt die Zwischenergebnisse ausgeben und vergleichen? Möglicherweise 
ein Problem mit unportablem Integer Verhalten. Mal mit "-Wall -Wextra 
-pedantic" kompilieren, vielleicht findet der Compiler das ja sogar...

von Rangi J. (rangi)


Lesenswert?

Habs gefunden!
ich hab die CRC des Chunks mit übergeben, also das zu bearbeitetende 
Array war 4 Bytes zu lange. Damit hat scheinbar der Adler ein Problem.
Jetzt gehts

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.