首页
下载
文档
社区
视频
捐赠
源代码
赞助商
AOT 编译器
AI 助理
商业产品
PHP AOT 原生编译器
Swoole-Compiler 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
strncpy的一些问题
swoole的代码中好多处地方使用了strncpy. strncpy函数存在两个缺陷 1:浪费CPU, 当src_size < dst_size的时候, 会复制(dst_size - src_size)个0, 实际上1个就够了 2,当src_size >= dst_size的时候,dst_size后来后面不会补0, 这个很容易导致bug. 我发现swoole中strncpy目前导致了两个问题 1,bug {{{ bzero(ls->host, SW_HOST_MAXSIZE); strncpy(ls->host, host, SW_HOST_MAXSIZE); }}} {{{ int swSocket_bind(int sock, int type, char *host, int port) { // ............ // 这里的host不一定以0结尾的, 有可能导致core dump. strcpy(addr_un.sun_path, host); // ............ } }}} 2 , 导致代码非常啰嗦 {{{ int get_spilt(char *pszSrc, char *pszSplit, char *pszDest, int nDestLen) { iPos = strlen(pszSrc); iPos = iPos > (nDestLen - 1) ? (nDestLen - 1): iPos; strncpy(pszDest, pszSrc, iPos); pszDest[iPos] = '\0'; // 这里可以用一句代码替代 strlcpy(pszDest, pszSrc, nDestLen); } }}} strlcpy 虽然不是标准函数, 但是目前在linux内核,chrome等大型工程都是事实上的标配。 可以引入一个函数来有效解决这个问题。 {{{ size_t swoole_strlcpy(char* dst, const char* src, size_t dst_size) { for (size_t i = 0; i < dst_size; ++i) { if ((dst[i] = src[i]) == 0) return i; } if (dst_size != 0) dst[dst_size - 1] = 0; while (src[dst_size]) ++dst_size; return dst_size; } }}} 现在的问题是, 我想提交代码 1, github pull request, 目前还没有人给swoole提交过。 2, 直接提交没有权限。 我的github是: https://github.com/cloudpeak
发布于8年前 · 0 次浏览 · 来自
提问
M
MR.Liu
swoole的代码中好多处地方使用了strncpy. strncpy函数存在两个缺陷 1:浪费CPU, 当src_size < dst_size的时候, 会复制(dst_size - src_size)个0, 实际上1个就够了 2,当src_size >= dst_size的时候,dst_size后来后面不会补0, 这个很容易导致bug. 我发现swoole中strncpy目前导致了两个问题 1,bug {{{ bzero(ls->host, SW_HOST_MAXSIZE); strncpy(ls->host, host, SW_HOST_MAXSIZE); }}} {{{ int swSocket_bind(int sock, int type, char *host, int port) { // ............ // 这里的host不一定以0结尾的, 有可能导致core dump. strcpy(addr_un.sun_path, host); // ............ } }}} 2 , 导致代码非常啰嗦 {{{ int get_spilt(char *pszSrc, char *pszSplit, char *pszDest, int nDestLen) { iPos = strlen(pszSrc); iPos = iPos > (nDestLen - 1) ? (nDestLen - 1): iPos; strncpy(pszDest, pszSrc, iPos); pszDest[iPos] = '\0'; // 这里可以用一句代码替代 strlcpy(pszDest, pszSrc, nDestLen); } }}} strlcpy 虽然不是标准函数, 但是目前在linux内核,chrome等大型工程都是事实上的标配。 可以引入一个函数来有效解决这个问题。 {{{ size_t swoole_strlcpy(char* dst, const char* src, size_t dst_size) { for (size_t i = 0; i < dst_size; ++i) { if ((dst[i] = src[i]) == 0) return i; } if (dst_size != 0) dst[dst_size - 1] = 0; while (src[dst_size]) ++dst_size; return dst_size; } }}} 现在的问题是, 我想提交代码 1, github pull request, 目前还没有人给swoole提交过。 2, 直接提交没有权限。 我的github是: https://github.com/cloudpeak
赞
0
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
登录
后参与评论
评论
2018-04-02
t
tracyp
感谢你的建议, 1. 既然用了strcpy就肯定保证是\0结尾的,host等参数是由PHP传入的,而PHP的字符串一定是\0结尾。所以不会出现core dump 2. strcpy和strlcpy的性能差异无关紧要,在swoole中绝大部分都是一次性操作,没必要为此进行优化 3. 标准库没有此函数
赞
0
回复
2018-04-02
P
Peter
感谢回复 1, 性能倒也不一定, 只是从C语言的角度这么一说,因为系统自带strncpy内部可能会使用CPU内置的向量机去完成。 2, 推理一下, strcpy(addr_un.sun_path, host); 是可能破坏堆栈, 导致异常的, 因为如果输入的host_len >= SW_HOST_MAXSIZE, 然后调用strncpy的话整个char host[SW_HOST_MAXSIZE]都是非0字节, host后面有一堆字段, 并不能保证host后面有0,也不应该依赖后面的字段来提供0,
赞
0
回复
2018-04-02
s
sky
再附加一条意见 swoole的timer queue用的是gettimeofday, 但是粗心的运维人员可能会粗暴的设置时间, 这样会导致timer 出现紊乱, 建议采用monotonic time, 这样增加程序的鲁棒性。golang早期的版本也有这个问题, 后来改用了单调的时间。
赞
0
回复
2018-04-02
张
张雷
accept4的情况下设置NONBLOCK和CLOEXEC, 但是accept的情况下只设置NONBLOCK, 建议一同设置CLOEXEC,否则一个设置一个不设置也不好看, 一般来讲, 默认CLOEXEC还是非常有必要的。 同样的情况, swClient_create中的socket也应该设置CLOEXEC, 还有Listener更是如此, 如果子进程没有退出,父进程重启后可能就没法bind端口。
赞
0
回复
2018-04-03
L
LOOP
http解析的部分似乎有不少问题,我之后提上来,刚接触不久, 如果是乌龙,还望作者海涵。
赞
0
回复
2018-04-04
z
zjh
* SIGUSR1 目前这个尚在实验阶段,底层信号处理确实是基于`signalfd`实现的。 * strcpy(addr_un.sun_path, host) 和 CLOEXEC设置 2项 已采纳 * monotonic time还在研究中
赞
0
回复
2018-04-04
z
zlg
swoole中多处调用了memcmp. {{{ if (memcmp(header_name, ZEND_STRL("content-type")) == 0) }}} 这样的用法会有问题, header_name虽然一定是'\0'结尾, 但是不能保证这样做是安全的 header_name来自用户输入,可能就只有一个字节,这种情况下调用memcmp可能导致segment fault, 因为memcmp内部并不是一个字节一个字节去比较的,而是采用一些向量指令,一次8个或者16个字节去比
赞
0
回复
2018-04-04
聚
聚米宋
感谢反馈,这里使用`memcmp`确实存在安全风险。请在这里提交issue,可以与commit对应起来。 [https://github.com/swoole/swoole-src/issues/new](https://github.com/swoole/swoole-src/issues/new)
赞
0
回复