You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 06:24:50