MENU

Fuck you, newlib 3.0.0 !!!

November 13, 2021 • 阅读: 1329 • 笔记&折腾

Fuck you, newlib 3.0.0 !!!

在对riscv-gcc进行正确性验证时发现某些库函数的功能性测试会发生错误,进行一系列排查后,发现是由newlib对函数接口的实现代码存在问题。

strtoimax() 接口
该接口在文件 ./newlib-3.0.0/newlib/libc/stdlib/strtoimax.c 中实现。
该接口用法及案例:https://www.apiref.com/cpp-zh/c/string/byte/strtoimax.html
错误测试案例代码:

#include <stdio.h>
#include <inttypes.h>
int main(){
        char* endptr;
        long long a;

        a = strtoimax("  -",&endptr,32);
        printf("a = %lld\n", a); 
        printf("endptr = '%s'\n", endptr);

        a = strtoimax(" -ab ",&endptr,11);
        printf("a = %lld\n", a); 
        printf("endptr = '%s'\n", endptr); 

        a = strtoimax("zzz",&endptr,36);
        printf("a = %lld\n", a); 
        printf("endptr = '%s'\n", endptr); 

        return 0;
}

本次测试中有3个案例,x86-gcc 编译运行的正确结果为:

a = 0
endptr = '  -'
a = -10
endptr = 'b '
a = 46655
endptr = ''

riscv-gcc 编译运行的结果为(riscv32-unknown-elf-gcc test.c -Os):

a = 0
endptr = ''
a = -1261578
endptr = 'b '
a = 5350929983
endptr = ''

经过一系列调试发现,./newlib-3.0.0/newlib/libc/stdlib/strtoimax.c 文件中对该函数的实现代码中,有两个变量 acc, any 未进行初始化:

const char *s = (const unsigned char *)nptr;
uintmax_t acc;
char c;
uintmax_t cutoff;
int neg = 0, any, cutlim;
...

由这个原因导致了接口后续代码运算时发生了错误。

该库函数的实现在之前的 newlib2.5.0 版本未被添加,在 newlib3.0.0 中首次添加,在后续的 newlib3.1.0 中该问题迅速被修补(对变量 acc 和 any 进行了初始化)。

const char *s = nptr;
uintmax_t acc = 0;
char c;
uintmax_t cutoff;
int neg = 0, any = 0, cutlim;
...

将 newlib3.0.0 切换成 newlib3.1.0~newlib4.1.0 之后再编译运行案例,已能正确获取结果。