Дано: CRC для хороших данных и CRC для данных с одним плохим байтом. Предполагается, что два заданных CRC являются хорошими, поэтому в самих CRC нет ошибок. Xor хороших данных CRC с плохими данными CRC. Рассматривайте это как ксерокопирование хороших данных + хороший CRC с плохими данными + плохой CRC, в результате получаются данные со всеми нулями, кроме одного плохого байта, и соответствующий CRC. Xor также отменяет любое начальное значение CRC или последующее дополнение значения CRC.
Для того, чтобы иметь возможность определять местоположение плохого байта, CRC должен быть уникальным для каждой возможной комбинации местоположения байта и значения байта.
Я обнаружил, что полином CRC32C 0x1edc6f41 создает уникальные CRC для данных от 1 до 190235 байт. Он завершается с ошибкой в 190236 байт данных, так как все нулевые буферы за исключением того, что bfr [0] = 0xfb или bfr [190235] = 0x32 оба выдают одинаковый (неуникальный) CRC = 0x364b1c30.
Пример кода для определения местоположения с хорошим CRC и плохим CRC (один плохой байт):
static uint32_t crcrtbl[256];
void genrtbl(void)
{
uint32_t crc;
uint32_t b;
uint32_t c;
uint32_t i;
for(c = 0; c < 0x100; c++){
crc = c;
for(i = 0; i < 8; i++){
b = crc&1;
crc >>= 1;
crc ^= (0 - b) & (0x11edc6f41>>1);
}
crcrtbl[c] = crc;
}
}
size_t crc32r(uint32_t crc, size_t size)
{
while(size--){
crc = (crc >> 8) ^ crcrtbl[crc & 0xff];
if(0 == (crc & 0xffffff))
break;
}
return(size);
}
// ...
genrtbl(); // generate table
// given good_crc and bad_crc, return location
location = crc32r(good_crc ^ bad_crc, size);
код для генерации crc
uint32_t crctbl[256];
void gentbl(void)
{
uint32_t crc;
uint32_t b;
uint32_t c;
uint32_t i;
for(c = 0; c < 0x100; c++){
crc = c<<24;
for(i = 0; i < 8; i++){
b = crc>>31;
crc <<= 1;
crc ^= (0 - b) & 0x1edc6f41; // 32 bit crc
}
crctbl[c] = crc;
}
}
uint32_t crc32(uint32_t crc32, uint8_t * bfr, size_t size)
{
uint32_t crc = crc32;
while(size--)
crc = (crc << 8) ^ crctbl[(crc >> 24)^*bfr++];
return(crc);
}