Adding to String not working correctly

I'm having an issue when using the += on two Strings does not seem to work correctly in one case only in my program, in the two other cases it works correctly.

For background, I am reading data 3 times from an RFID tag using the MFRC522 library, but I am fairly sure the issue is not hardware or library related. Each time I read from the tag, I take the value read (as a String) and use += to append it to a global String (named hash).

Here's the code:

#include <SPI.h>
#include <MFRC522.h>
 
#define SS_PIN 7
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

byte blockOne = 4;
byte blockTwo = 5;
byte blockThree = 6;

String hash;

MFRC522::MIFARE_Key newKeyA = {keyByte: {0xB4, 0xF7, 0xA1, 0xD3, 0xE5, 0xB1}};
MFRC522::MIFARE_Key newKeyB = {keyByte: {0xB0, 0xF0, 0xFF, 0xA3, 0xB5, 0xC1}};
MFRC522::StatusCode status;

bool readBytesFromBlock(byte block) {
  byte buffer1[18];
  byte len = 18;
  
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &newKeyA, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Authentication failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }
 
  status = mfrc522.MIFARE_Read(block, buffer1, &len);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Reading failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }
 
  String value = "";
  for (uint8_t i = 0; i < 16; i++)
  {
      value += (char)buffer1[i];
  }
  value.trim();
  Serial.print(value);
 
  Serial.println(F("\n**End Reading**\n"));

  delay(400);

  hash += value;

  return true;
}

void setup() {
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus

  mfrc522.PCD_Init();   // Initiate MFRC522 RFID

  Serial.println("setup finished");
}

void loop() {
    // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
    delay(50);
    return;
  }
Serial.println("Try To Authenticate");
    if (readBytesFromBlock(blockOne)) {
      Serial.print("current hash value: ");
      Serial.println(hash);
      readBytesFromBlock(blockTwo);
      Serial.print("current hash value: ");
      Serial.println(hash);
      readBytesFromBlock(blockThree);
      Serial.print("current hash value: ");
      Serial.println(hash);
    }
    else {
      // reading failed; card was moved from reader or is not registered
      Serial.println(" Access denied");
      delay(3000);
      hash = "";
      return;
    }
    Serial.print("final hash: ");
    Serial.println(hash);
    hash = "";
    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();
}

Here's the output:

setup finished
Try To Authenticate
He14foZhZNsRNDl2
**End Reading**

current hash value: He14foZhZNsRNDl2
2s4EsohQB3/jK08
**End Reading**

current hash value: He14foZhZNsRNDl2k3cEnyWEHe14fo
HnsDc32k3cEnyWE
**End Reading**

current hash value: He14foZhZNsRNDl22k3cEnyWEHe14foHnsDc32k3cEnyWE
final hash: He14foZhZNsRNDl22k3cEnyWEHe14foHnsDc32k3cEnyWE

So as you can see, one the second call of readBytesFromBlock, the value read in from the RFID tag and what is added to the String hash is different. The final value of hash should be He14foZhZNsRNDl22s4EsohQB3/jK08HnsDc32k3cEnyWE, instead of He14foZhZNsRNDl22k3cEnyWEHe14foHnsDc32k3cEnyWE

Can anyone help me learn why this is happening for just this one call of the method?

one more reason why you should not use the String class in the first place :slight_smile:

have you noticed that

He14foZhZNsRNDl2 has 16 characters
2s4EsohQB3/jK08 has only 15 although you read 16 of them
HnsDc32k3cEnyWE has only 15 although you read 16 of them

is there something missing ?
(could there be a non ascii code that would have triggered a UTF8 representation ?)

--> can you print the Hex value of the byte you add to build up your string

bool readBytesFromBlock(byte block) {
  byte buffer1[18];
  byte len = 18;

  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &newKeyA, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Authentication failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }

  status = mfrc522.MIFARE_Read(block, buffer1, &len);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Reading failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return false;
  }

  Serial.print(F("len = "));
  Serial.println(len);
  String value = "";

  Serial.print(F("bytes => "));
  for (uint8_t i = 0; i < 16; i++)
  {
    Serial.print(F("0x"));
    Serial.print(buffer1[i], HEX);
    Serial.print(F(" "));
    value += (char)buffer1[i];
  }
  Serial.println();

  value.trim();
  Serial.print(value);

  Serial.println(F("\n**End Reading**\n"));

  delay(400);

  hash += value;

  return true;
}

PS: you really could do without the String class there, you have char buffers coming in, it would be just a matter of reading all the bytes in the right place and add a trailing '\0' to have a proper cString...