C语言实现海绵结构时触发Segmentation fault的问题排查
问题分析与解决方案
核心问题原因
- 数组越界访问触发内存污染:
status_permutieren函数的循环从i=0开始,此时status[i - 16 + j]等价于status[-16 + j],属于非法越界访问,会破坏内存中其他区域的数据,导致后续subbytes函数中list[i]的值超出tab数组的合法索引范围(0-255),最终触发Segmentation fault。 - 未确保下标合法性:
tab数组仅有256个元素,但list[i]是int类型,若其值为负数或大于255,直接作为下标访问tab会导致越界错误。
修复步骤
1. 修正status_permutieren的循环起始值
将循环起始i从0改为16,避免访问status数组以外的内存:
void status_permutieren() { int temp[16]; // 从i=16开始,确保i-16为合法下标(0 <= i-16 < 208) for (int i = 16; i < 208; i += 16) { for (int j = 0; j < 16; j++) { status[i + j] ^= status[i - 16 + j]; temp[j] = status[i + j]; } prp(temp, &status[i]); } }
2. 强制保证tab下标在合法范围
在subbytes函数中,将list[i]强制转换为unsigned char,确保其值落在0-255之间:
void subbytes(int *list, int *result) { for (int i = 0; i < 16; i++) { // 强制转换为无符号字节,避免负数或超范围值作为下标 result[i] = tab[(unsigned char)list[i]]; } }
3. 可选:添加断言调试(快速定位非法下标)
可以加入断言,在调试阶段快速发现非法下标问题:
#include <assert.h> // 需要包含此头文件 void subbytes(int *list, int *result) { for (int i = 0; i < 16; i++) { unsigned char idx = (unsigned char)list[i]; assert(idx < sizeof(tab)/sizeof(tab[0])); // 断言下标合法 result[i] = tab[idx]; } }
修正后的完整代码(关键部分已修改)
#include <stdio.h> #include <assert.h> // 可选,用于调试断言 int tab[] = {129, 160, 71, 24, 142, 254, 178, 152, 182, 53, 190, 133, 149, 187, 56, 14, 198, 62, 192, 118, 121, 4, 125, 146, 90, 207, 66, 31, 19, 7, 132, 114, 68, 202, 208, 80, 37, 40, 134, 58, 111, 42, 250, 105, 180, 41, 156, 155, 166, 211, 170, 215, 165, 69, 88, 23, 6, 141, 226, 186, 35, 28, 54, 193, 89, 92, 230, 120, 44, 59, 64, 237, 151, 91, 116, 171, 87, 115, 26, 137, 67, 78, 194, 5, 29, 167, 189, 17, 253, 124, 238, 65, 184, 30, 185, 220, 84, 172, 123, 174, 18, 117, 153, 150, 128, 74, 162, 98, 212, 231, 159, 242, 206, 93, 188, 46, 76, 243, 147, 240, 219, 179, 139, 246, 255, 130, 195, 99, 161, 183, 245, 22, 140, 45, 173, 163, 148, 33, 20, 47, 216, 131, 12, 72, 223, 32, 145, 94, 249, 96, 205, 10, 157, 57, 95, 136, 138, 218, 229, 0, 122, 107, 126, 113, 109, 127, 158, 168, 210, 236, 204, 112, 191, 252, 104, 48, 73, 79, 197, 52, 108, 176, 38, 102, 100, 164, 247, 61, 2, 241, 43, 224, 119, 75, 63, 25, 143, 225, 97, 217, 106, 203, 110, 49, 200, 1, 39, 233, 3, 214, 81, 209, 60, 244, 34, 154, 239, 9, 101, 232, 235, 85, 83, 50, 86, 169, 51, 222, 251, 175, 144, 135, 16, 70, 248, 15, 82, 234, 27, 228, 8, 55, 21, 221, 36, 196, 177, 77, 227, 199, 213, 13, 201, 11, 103, 181}; int status[208]; void mixRows_gerade_runde_(int *liste, int *result) { result[0] = (liste[0] ^ 0xd3); result[1] = (liste[1] ^ liste[0] ^ 0xd3); result[2] = (liste[2] ^ liste[1] ^ liste[0] ^ 0xd3); result[3] = (liste[3] ^ liste[2] ^ liste[1] ^ liste[0] ^ 0xd3); result[4] = (liste[4] ^ 0xd4); result[5] = (liste[5] ^ liste[4] ^ 0xd4); result[6] = (liste[6] ^ liste[5] ^ liste[4] ^ 0xd4); result[7] = (liste[7] ^ liste[6] ^ liste[5] ^ liste[4] ^ 0xd4); result[8] = (liste[8] ^ 0xd5); result[9] = (liste[9] ^ liste[8] ^ 0xd5); result[10] = (liste[10] ^ liste[9] ^ liste[8] ^ 0xd5); result[11] = (liste[11] ^ liste[10] ^ liste[9] ^ liste[8] ^ 0xd5); result[12] = (liste[12] ^ 0xd6); result[13] = (liste[12] ^ liste[13] ^ 0xd6); result[14] = (liste[12] ^ liste[13] ^ liste[14] ^ 0xd6); result[15] = (liste[12] ^ liste[13] ^ liste[14] ^ liste[15] ^ 0xd6); } void mixRows_ungerade_runde_(int *liste, int *result) { result[0] = (liste[3] ^ liste[2] ^ liste[1] ^ liste[0] ^ 0xd3); result[1] = (liste[3] ^ liste[2] ^ liste[1] ^ 0xd3); result[2] = (liste[3] ^ liste[2] ^ 0xd3); result[3] = (liste[3] ^ 0xd3); result[4] = (liste[7] ^ liste[6] ^ liste[5] ^ liste[4] ^ 0xd4); result[5] = (liste[5] ^ liste[7] ^ liste[6] ^ 0xd4); result[6] = (liste[7] ^ liste[6] ^ 0xd4); result[7] = (liste[7] ^ 0xd4); result[8] = (liste[8] ^ liste[9] ^ liste[10] ^ liste[11] ^ 0xd5); result[9] = (liste[9] ^ liste[11] ^ liste[10] ^ 0xd5); result[10] = (liste[10] ^ liste[11] ^ 0xd5); result[11] = (liste[11] ^ 0xd5); result[12] = (liste[12] ^ liste[13] ^ liste[14] ^ liste[15] ^ 0xd6); result[13] = (liste[13] ^ liste[14] ^ liste[15] ^ 0xd6); result[14] = (liste[14] ^ liste[15] ^ 0xd6); result[15] = (liste[15] ^ 0xd6); } void liste_zu_status(int *list) { for (int i = 0; i < 16; i++) { status[i] ^= list[i]; } } void subbytes(int *list, int *result) { for (int i = 0; i < 16; i++) { unsigned char idx = (unsigned char)list[i]; assert(idx < sizeof(tab)/sizeof(tab[0])); result[i] = tab[idx]; } } void shift_colums(int *list, int *result) { result[0] = list[0]; result[1] = list[13]; result[2] = list[10]; result[3] = list[7]; result[4] = list[4]; result[5] = list[1]; result[6] = list[14]; result[7] = list[11]; result[8] = list[8]; result[9] = list[5]; result[10] = list[2]; result[11] = list[15]; result[12] = list[12]; result[13] = list[9]; result[14] = list[6]; result[15] = list[3]; } void prp(int *block, int *result) { int temp[16]; subbytes(block, temp); mixRows_gerade_runde_(temp, result); shift_colums(result, temp); subbytes(temp, result); mixRows_gerade_runde_(result, temp); shift_colums(temp, result); subbytes(result, temp); mixRows_ungerade_runde_(temp, result); shift_colums(result, temp); subbytes(temp, result); mixRows_ungerade_runde_(result, temp); shift_colums(temp, result); subbytes(temp, result); mixRows_ungerade_runde_(result, temp); shift_colums(temp, result); subbytes(temp, result); } void status_permutieren() { int temp[16]; for (int i = 16; i < 208; i += 16) { for (int j = 0; j < 16; j++) { status[i + j] ^= status[i - 16 + j]; temp[j] = status[i + j]; } prp(temp, &status[i]); } } void block_absorbieren(int *block) { for (int i = 0; i < 16; i++) { status[i] ^= block[i]; } status_permutieren(); } void status_zuruecksetzen() { for (int i = 0; i < 208; i++) { status[i] = 0; } } void daten_absorbieren(int *daten, int len) { int temp[16]; for (int i = 0; i < len; i += 16) { for (int j = 0; j < 16; j++) { temp[j] = (i + j < len)? daten[i + j] : 0; } block_absorbieren(temp); } } void daten_generieren(int menge, int *ergebnis) { for (int i = 0; i < menge; i++) { ergebnis[i] = status[207] ^ status[206] ^ ~status[202] & status[197] | status[196] ^ status[189]; status_permutieren(); } } int main() { printf("starting\n"); // Initialize status array with zeros for (int i = 0; i < 208; i++) { status[i] = 0; } // Example usage int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int generated_data[10]; // Absorb data daten_absorbieren(data, sizeof(data) / sizeof(data[0])); // Generate data daten_generieren(10, generated_data); // Print generated data printf("Generated data:\n"); for (int i = 0; i < 10; i++) { printf("%d ", generated_data[i]); } printf("\n"); return 0; }
内容的提问来源于stack exchange,提问作者Ruben Wulf
相关产品推荐
相关产品推荐

