PostgreSQL C扩展调用约定异常:RGB类型输入输出值不符
问题分析与修复方案
核心错误原因
你的问题由两个关键代码错误导致:
1. RGB范围校验逻辑完全错误
在rgb_in函数中,你使用**逻辑或||**判断颜色值是否合法:
if (in_range(r) || in_range(g) || in_range(b)) { ... }
这意味着只要有一个颜色值在0-255范围内,就会赋值所有值,非法值(如十六进制解析出错得到的负数)也会被写入结构体,直接导致后续读取到异常数据。
2. rgb_out中snprintf缓冲区大小参数错误
你使用sizeof(result)作为缓冲区大小:
int len = snprintf(result, sizeof(result), "#%02X%02X%02X", ...);
result是指针类型,sizeof(result)返回的是指针的字节数(通常8字节),而非你用palloc分配的RGB_STR_LEN + 1字节。这会导致缓冲区溢出,破坏内存中存储的RGB结构体数据,读取时出现垃圾值。
修复步骤
修复范围校验逻辑
将rgb_in中的逻辑或改为逻辑与&&,确保三个颜色值都合法才赋值:
// 替换原有的范围判断代码 if (in_range(r) && in_range(g) && in_range(b)) { result->red = (int32)r; result->green = (int32)g; result->blue = (int32)b; } else { ereport(ERROR, (errmsg("RGB values must be >= 0 and <= 255"))); }
修复snprintf缓冲区大小
使用实际分配的内存大小作为缓冲区限制:
// 替换原有的snprintf调用 char *result = (char *)palloc(RGB_STR_LEN + 1); int len = snprintf(result, RGB_STR_LEN + 1, "#%02X%02X%02X", rgb->red, rgb->green, rgb->blue);
额外优化:提前处理非法十六进制字符
当前hex_to_int返回-1表示非法字符,但你没有在解析时检查这个结果。可以在解析十六进制值时添加校验,提前报错:
// 在rgb_in的十六进制解析分支中添加校验 int r1 = hex_to_int(str[1]); int r2 = hex_to_int(str[2]); if (r1 == -1 || r2 == -1) { ereport(ERROR, (errmsg("Invalid hexadecimal character in RGB value: \"%s\"", str))); } int r = (r1 << 4) + r2; // 对g、b做同样的校验
为什么to_rgb函数能正常工作?
to_rgb直接接收合法的整数参数,没有范围校验的逻辑错误,也没有缓冲区溢出问题,因此内存中的RGB结构体数据未被破坏,rgb_out能正确读取。
内容的提问来源于stack exchange,提问作者λ Jonas Gorauskas
相关产品推荐
相关产品推荐

