ILD

a integer overflow bug
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2024-4-26 站点:Inside Linux Development

最近碰到了一个整数溢出的问题,排查了半天


代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct fs_opened {
        int slice_size;
        int next_slice;
        ...
}
 
static int start_upload(struct dlife_cloud *cloud, struct fs_opened *opened, int64_t file_size)
{
        int64_t uploaded_size = opened->next_slice * opened->slice_size;
        int64_t remain_size = file_size - uploaded_size;
        int upload_size = MIN(remain_size, opened->slice_size);
 
        if (upload_size == 0 || rb_len(&opened->rb) < upload_size)
                return 0;
         
        ...
}


文件按块分片上传,一个块是10M,所以opened->slice_size的值是:10*1024*1024,opened->next_slice的值是已经上传的块,

上面的逻辑很简单,用文件大小减去已经上传的大小,得到剩余待上传的大小remain_size,然后和分片10M比较,取最小值,得到当前上传分片的大小。rb_len()是缓存的大小,如果缓存够了,就触发上传。


上传一个3G多的文件,最后一个块传输不了,从上面return 0返回了,最后一个分片打印出来upload_size是10M,而不是最后一个片剩余的大小,百思不得其解,最后加了详细的打印,发现是

1
int64_t uploaded_size = opened->next_slice * opened->slice_size;

计算溢出了。


slice_size: 10*1024*1024

next_silice: 324


他们都是32位整数,相乘赋值给64位整数,但是乘的时候已经溢出了,得到uploaded_size是:-897581056,导致remain_size计算错误。

导致最后一个片,认为是没有足够的缓存,而没有触发上传。


总结:

int64 = int * int 

这种形式会存在整数计算溢出,需要小心。




Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.