[知其然不知其所以然-26] Why shouldn't you use IS_ERR_VALUE
2016-05-28 14:01
435 查看
Beware of the IS_ERR_VALUE, you should not use it to check if function returns any errno code,
instead, you can only use IS_ERR_VALUE for pointer validation, and use if(ret) to verify whether
the function succeed or not.
https://patchwork.ozlabs.org/patch/627363/
OK, we can see from the compiling error, int and unsigned int are both expanded, while int
is signed expanded,so it is still -EPERM after expanded to 64bits, while for unsigned int,it is expanded
as unsigned, so the value becomes a valid one, (it is smaller than 0xffffffff),because the higher 32bits are
filled with zero, without setting the bit63 to 1.
instead, you can only use IS_ERR_VALUE for pointer validation, and use if(ret) to verify whether
the function succeed or not.
https://patchwork.ozlabs.org/patch/627363/
Most users of IS_ERR_VALUE() in the kernel are wrong, as they pass an 'int' into a function that takes an 'unsigned long' argument. This happens to work because the type is sign-extended on 64-bit architectures before it gets converted into an unsigned type. However, anything that passes an 'unsigned short' or 'unsigned int' argument into IS_ERR_VALUE() is guaranteed to be broken, as are 8-bit integers and types that are wider than 'unsigned long'.
cat test_is_err_value.c #include <stdio.h> #define MAX_ERRNO 4095 #define IS_ERR_VALUE(x) ((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO) #define EPERM 1 #define ENOENT 2 int main(int argc, char *argv[]) { int test_0 = -EPERM; unsigned int test_1 = -ENOENT; if (IS_ERR_VALUE(test_0)) printf("test_0 invalid\n"); else printf("test_0 valid\n"); if (IS_ERR_VALUE(test_1)) printf("test_1 invalid\n"); else printf("test_1 valid\n"); return 0; }
gcc test_is_err_value.c -o test_is_err_value test_is_err_value.c: In function ‘main’: test_is_err_value.c:3:41: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] #define IS_ERR_VALUE(x) ((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO) ^ test_is_err_value.c:12:6: note: in expansion of macro ‘IS_ERR_VALUE’ if (IS_ERR_VALUE(test_0)) ^ test_is_err_value.c:3:41: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] #define IS_ERR_VALUE(x) ((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO) ^ test_is_err_value.c:16:6: note: in expansion of macro ‘IS_ERR_VALUE’ if (IS_ERR_VALUE(test_1)) ^
OK, we can see from the compiling error, int and unsigned int are both expanded, while int
is signed expanded,so it is still -EPERM after expanded to 64bits, while for unsigned int,it is expanded
as unsigned, so the value becomes a valid one, (it is smaller than 0xffffffff),because the higher 32bits are
filled with zero, without setting the bit63 to 1.
./test_is_err_value test_0 invalid test_1 valid
相关文章推荐
- 访问Nginx发生SSL connection error的一种情况
- 星外虚拟主机访问被控出现Unspecified error解决方法
- IIS 错误 Server Application Error 详细解决方法
- On Error Resume Next 语句
- IIS运行错误 Server Application Error 错误代码 Error: 8004的解决方法
- Lua编程示例(一):select、debug、可变参数、table操作、error
- 收集整理的http/1.1 500 server error错误的解决方法
- SQL 2005 ERROR:3145 解决办法(备份集中的数据库备份与现有的数据库不同)
- VBScript中On Error语句用法小结
- 解决VC++编译报错error C2248的方案
- jQuery Uploadify 上传插件出现Http Error 302 错误的解决办法
- JQuery ajax中error返回错误及一直返回error的解答
- PHP函数之error_reporting(E_ALL ^ E_NOTICE)详细说明
- node.js使用npm 安装插件时提示install Error: ENOENT报错的解决方法
- PHP 5.3和PHP 5.4出现FastCGI Error解决方法
- 解决mysql ERROR 1017:Can't find file: '/xxx.frm' 错误
- MYSQL ERROR 1045 (28000): Access denied for user (using password: YES)问题的解决
- vs2012 error c4996: This function or variable may be unsafe
- php异常:Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE eval()'d code error
- ERROR/AndroidRuntime(17121)的问题解决