qicosmos / cinatra

modern c++(c++20), cross-platform, header-only, easy to use http framework
MIT License
1.82k stars 369 forks source link

bug: gcc resize_and_overwrite 導致髒數據的問題 #509

Closed hoskylucky closed 5 months ago

hoskylucky commented 5 months ago

hi,我在使用cinatra的時候會遇到一些問題,在http read request的時候body會有髒數據,檢查了一下發現發生問題的地方出在details::resize中,gcc的resize_and_overwrite貌似會返回capacity,在stackoverflow中有討論,并且gcc bugzilla也有提到。 我使用的環境爲ubuntu 22.04 / gcc 13.2/ cinatra 0.8.3 感謝。

qicosmos commented 5 months ago

谢谢报告,稍晚看一下。

poor-circle commented 5 months ago

hi,我在使用cinatra的時候會遇到一些問題,在http read request的時候body會有髒數據,檢查了一下發現發生問題的地方出在details::resize中,gcc的resize_and_overwrite貌似會返回capacity,在stackoverflow中有討論,并且gcc bugzilla也有提到。 我使用的環境爲ubuntu 22.04 / gcc 13.2/ cinatra 0.8.3 感謝。

我们现在没有用到这个函数提供的sz啊

qicosmos commented 5 months ago

有测试代码?需要复现查问题。

hoskylucky commented 5 months ago

cinatra這裏用到了resize,裏面是用std::base_string::resize_and_overwrite進行string的内存擴展(std=c++23),作者的blog也有提到,測試代碼

poor-circle commented 5 months ago

问题是我们不会用到返回值

poor-circle commented 5 months ago

所以问题出在别的地方。 你能否提供一段测试代码?

hoskylucky commented 5 months ago

這時候的size預期設置爲25,但是實際上設置成了30,在後面使用memcpy沒有#0,導致多出來的内存可能被外面讀成髒數據。

poor-circle commented 5 months ago

這時候的size預期設置爲25,但是實際上設置成了30,在後面使用memcpy沒有#0,導致多出來的内存可能被外面讀成髒數據。

實際上設置成了30-> 指的是string的容量?

hoskylucky commented 5 months ago

是的,string.size()是大於body_len的,但是後面沒有/0,所以外面可能讀出髒數據

poor-circle commented 5 months ago

是的,string.size()是大於body_len的,但是後面沒有/0,所以外面可能讀出髒數據

你指的是string::size()大于body_len还是string::capacity()大于body_len

poor-circle commented 5 months ago

這時候的size預期設置爲25,但是實際上設置成了30,在後面使用memcpy沒有#0,導致多出來的内存可能被外面讀成髒數據。

我理解,代码期望的行为可能是,

1.body_len==25, size()==25, capacity()==30,然后data[25]=='\0',后面跟4个字节的脏数据。这是正常的。

如果出问题,可能是:

  1. body_len==25, size()==25, capacity()==30,但是data[25]是脏数据而不是\0
  2. body_len==25, size()==30, capacity()==30. 在你的测试代码中是哪种情况呢?
hoskylucky commented 5 months ago

這時候的size預期設置爲25,但是實際上設置成了30,在後面使用memcpy沒有#0,導致多出來的内存可能被外面讀成髒數據。

我理解,代码期望的行为可能是,size()==25, capacity()==30,然后data[25]=='\0',后面跟4个字节的脏数据。这是正常的。

是的這個行爲是正常的,但是在使用memcpy的時候僅拷貝了body_len爲25的字節,後面沒有\0,就變成了5個字節的髒數據。 現在是bodylen是25,size()是30,capacity()是30,使用memcpy拷貝了25字節,應該是拷貝25+1個字節,把\0算上。 不知道我是否描述清楚了。

poor-circle commented 5 months ago

這時候的size預期設置爲25,但是實際上設置成了30,在後面使用memcpy沒有#0,導致多出來的内存可能被外面讀成髒數據。

我理解,代码期望的行为可能是,size()==25, capacity()==30,然后data[25]=='\0',后面跟4个字节的脏数据。这是正常的。

是的這個行爲是正常的,但是在使用memcpy的時候僅拷貝了body_len爲25的字節,後面沒有\0,就變成了5個字節的髒數據。 現在是bodylen是25,size()是30,capacity()是30,使用memcpy拷貝了25字節,應該是拷貝25+1個字節,把\0算上。 不知道我是否描述清楚了。

@qicosmos

poor-circle commented 5 months ago

這時候的size預期設置爲25,但是實際上設置成了30,在後面使用memcpy沒有#0,導致多出來的内存可能被外面讀成髒數據。

我理解,代码期望的行为可能是,size()==25, capacity()==30,然后data[25]=='\0',后面跟4个字节的脏数据。这是正常的。

是的這個行爲是正常的,但是在使用memcpy的時候僅拷貝了body_len爲25的字節,後面沒有\0,就變成了5個字節的髒數據。 現在是bodylen是25,size()是30,capacity()是30,使用memcpy拷貝了25字節,應該是拷貝25+1個字節,把\0算上。 不知道我是否描述清楚了。

這時候的size預期設置爲25,但是實際上設置成了30,在後面使用memcpy沒有#0,導致多出來的内存可能被外面讀成髒數據。

我理解,代码期望的行为可能是,size()==25, capacity()==30,然后data[25]=='\0',后面跟4个字节的脏数据。这是正常的。

是的這個行爲是正常的,但是在使用memcpy的時候僅拷貝了body_len爲25的字節,後面沒有\0,就變成了5個字節的髒數據。 現在是bodylen是25,size()是30,capacity()是30,使用memcpy拷貝了25字節,應該是拷貝25+1個字節,把\0算上。 不知道我是否描述清楚了。

所以是这三种情况的哪一种呢?

poor-circle commented 5 months ago

1.body_len==25, size()==25, capacity()==30,然后data[25]=='\0',后面跟4个字节的脏数据。这是正常的。

  1. body_len==25, size()==25, capacity()==30,但是data[25]是脏数据而不是\0
  2. body_len==25, size()==30, capacity()==30.
hoskylucky commented 5 months ago

1.body_len==25, size()==25, capacity()==30,然后data[25]=='\0',后面跟4个字节的脏数据。这是正常的。 2. body_len==25, size()==25, capacity()==30,但是data[25]是脏数据而不是\0 3. body_len==25, size()==30, capacity()==30.

  1. body_len==25, size()==30, capacity()==30, 但是data[25]是脏数据而不是\0
qicosmos commented 5 months ago

能给个测试cinara的代码吗,先不纠结resize这里,我希望有个实际的例子能复现问题。@hoskylucky

poor-circle commented 5 months ago

我懂了,等下会提一个pr fix

poor-circle commented 5 months ago

https://godbolt.org/z/EefoE751z

我理解问题以及修复方案是这样的

qicosmos commented 5 months ago

用这个pr https://github.com/qicosmos/cinatra/pull/512 验证一下 @hoskylucky

hoskylucky commented 5 months ago

這樣就沒問題了,感謝。