Problem mir C-Pointer oder Brett vorm Kopf

Gast #6646218
Lesenswert?

Hallo,

ich habe ein Problem mit einem Base64 Beispielcode bzw einen Konten im 
Kopf.

das Beispiel:
1
char * toDecode = "SGVsbG8gV29ybGQgVGVzdGluZyBiYXNlNjQgZW5jb2Rpbmch";
2
uint16_t test = 40;
3
size_t outputLength;
4
unsigned char * decoded = base64_decode((const unsigned char *)toDecode, test, &outputLength);
5
Serial.print("Length of decoded message: ");
6
Serial.println(outputLength);
7
   
8
Serial.printf("%.*s", outputLength, decoded);
9
free(decoded);

Das Beispiel funktioniert einwandfrei.

Aber ich möchte ein uint8_t [] array decodieren und am liebsten auch ein 
array zurückbekommen.

Aber mein Controller rebootet sobald ich es mit einem Array als input 
versuche
1
char * toDecode = &input[0];
2
uint16_t test = 40;
3
size_t outputLength;
4
unsigned char * decoded = base64_decode((const unsigned char *)toDecode, test, &outputLength);
5
Serial.print("Length of decoded message: ");
6
Serial.println(outputLength);
7
   
8
Serial.printf("%.*s", outputLength, decoded);
9
free(decoded);

kann mir jemand sagen wo mein Denkfehler liegt?
(Firma: Golden Delicious Computers) #6646228
Lesenswert?

in "input".
1) enthält das wirklich einen base64-String?
2) was passiert wirklich wenn nicht (decoded == NULL)? Vermutlich 
Serial.printf(..., NULL).
3) welches System? Welcher Compiler? Aus welcher library stammt 
base64_decode()?
4) Was sagt das Manual zum Parameter wo die Variable "test" (aber mit 
Konstantem Wert 40) übergeben wird?
Gast #6646240
Lesenswert?

Nikolaus S. schrieb:
> in "input".
> 1) enthält das wirklich einen base64-String?
> 2) was passiert wirklich wenn nicht (decoded == NULL)? Vermutlich
> Serial.printf(..., NULL).
> 3) welches System? Welcher Compiler? Aus welcher library stammt
> base64_decode()?
> 4) Was sagt das Manual zum Parameter wo die Variable "test" (aber mit
> Konstantem Wert 40) übergeben wird?

1) Ja,
1
uint8_t * toDecode = &ble_rx[0];
2
    Serial.printf("%.*s", ble_rx_counter, toDecode);
Ausgabewert: AAECAwQFBgcICQoLDA0ODx

2) Length of decoded message: 2148463512
-> Also viel zu lang
-> direkt danach stürzt der controller ab

3) ESP32 mit der Aktuellen Arduino Library

4) Das original beispiel nimmt strlen()
Ich habe es schon auf eine variable geändert und es funktioniert damit.

Das Array mit der Base64 kodierung kommt per BLE. Ich erhalte ein 
uint8_t array und einen uint16 counter wieviele Bytes per BLE empfangen 
wurden
Gast #6646280
Lesenswert?

Der zweite Parameter von base64_decode ist die Länge des Eingabebuffers.
1
>   char * toDecode = &input[0];
2
>   uint16_t test = 40;
3
>   ...
4
>   ... base64_decode((const unsigned char *)toDecode, test, &outputLength);

Wenn das input-Array nicht mindestens 40 Zeichen lang ist, kann es 
knallen, ja.
Gast #6646286
Lesenswert?

Hallo Stefan,

hier die Hex Werte des Strings:

Data (23) is written to  Device Status Service: 41 41 45 43 41 77 51 46 
42 67 63 49 43 51 6F 4C 44 41 30 4F 44 78 0

der ble_rx_counter ist 23 und das letzte Byte ist 0
Gast #6646305
Lesenswert?

foobar schrieb:
> Der zweite Parameter von base64_decode ist die Länge des Eingabebuffers.
>>   char * toDecode = &input[0];
>>   uint16_t test = 40;
>>   ...
>>   ... base64_decode((const unsigned char *)toDecode, test, &outputLength);
>
> Wenn das input-Array nicht mindestens 40 Zeichen lang ist, kann es
> knallen, ja.

danke foobar

hier leigt anscheinend der fehler. Ich habe die Länge mal fest auf 20 
gesetzt (23 Bytes kriege ich ja) und es geht.

jetzt muss ich mir mal das array von decoded ausgeben lassen
Gast #6646311
Lesenswert?

> Data (23) is written to  Device Status Service: 41 41 45 43 41 77 51 46
> 42 67 63 49 43 51 6F 4C 44 41 30 4F 44 78 0

Wenn hinten immer eine 0 hängt, sollte der Code so sein:
1
   char *toDecode = &input[0];
2
   uint16_t inputLength = strlen(toDecode);
3
   ...
4
   ... base64_decode((const unsigned char *)toDecode, inputLength, &outputLength);
Gast #6646343
Lesenswert?

komisch

mit 20 gehts
mit 21,22,23 geht's nicht

Aber die Ausgabe sah auf den ersten Blick gut aus.

Vielleucht liegt's daran:

die .bin Datei wird von der App gelsen und komplett in Base64 kodiert.
Das ganze wird dann in BLE Packete geteilt. jedes BLE paket endet mit 
0x00

Morgen werde ich weiter testen

Schonmal vielen Dank an euch
Moderator #6646368
Lesenswert?

anfänger schrieb:
> mit 20 gehts
> mit 21,22,23 geht's nicht

Dann liegt es daran, dass das Padding fehlt. Dazu musst du die Länge des
Base64-kodierten Strings am Ende mit 0 bis 2 '='-Zeichen auffüllen, so
dass die Gesamtlänge ein Vielfaches von 4 wird.

Probier also mal

  AAECAwQFBgcICQoLDA0ODx==   (Länge 24 durch 4 teilbar)

statt

  AAECAwQFBgcICQoLDA0ODx     (Länge 22)

zu dekodieren. Das dekodierte Ergebnis sollten 16 Bytes mit den Werten
0, 1, 2, ... 15 sein.

PS: Normalerweise sollte der Kodierer das Padding vornehmen. Umgekehrt
gibt es auch tolerante Dekodierer, die ohne das Padding auskommen. In
deinem Fall haben wir es wohl einen laxen Kodierer und einen peniblen
Dekodierer zu tun :)

PS2: Da fehlt nicht nur das Padding, der Eingabestring scheint auch
sonst unvollständig zu sein. Würde nur das Padding fehlen, wären die
letzten 4 Bits alle 0, d.h. das letzte Zeichen wäre kein 'x', sondern
ein 'w'.
Gast #6646387
Lesenswert?

Du kannst nicht einfach Teile eines Base64-kodierten Datenstrom 
häppchenweise in den Dekoder schicken.  Wie dirkb2 schrieb, müssen es 
immer ein mehrfaches von 4-Byte-Paketen sein (pro 4 Byte rein kommen 3 
Byte raus).  Kürzere Bröckchen mit "=" auffüllen klappt nur am Ende des 
gesamten Datenstroms (das macht der Encoder normalerweise von selbst) - 
wenn man das mittendrin macht, kommen fehlerhafte Daten raus.
#6646393
Lesenswert?

Ohne die Funktion base64_decode zu kennen ist das nur ein Rätsel raten.
Die Funktion soll ein Array zurückliefern, aber wo wird es gespeichert?

Liefert sie gleichviel oder weniger Bytes zurück, könnte das der 
Eingabestring sein. Dann braucht man aber auch den Rückgabewert nirgends 
zuzuweisen.
Ist der Eingabestring von der Kommandozeile des OS, dann wird er 
read-only sein, d.h. Schreiben ergibt eine Exception.
Gast #6646963
Lesenswert?

Vielen Dank nochmal an alle

die Hinweise zu den 4 Bytes waren Goldrichtig

Ich habe die App angepasst und teile nun den Base64 String (insgesamt 
349 Bytes) in 20 Byte Stücke
jetzt funktioniert auch das dekodieren ohne Reboot

P.s. im ESP32 Gitter wurde empfohlen eine andere Base64 decode funktion 
zu nutzen.
1
int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen );

das probiere ich mal bei Gelegenheit aus.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren