[問題] 請問如何偵測 memcpy 的錯誤

看板C_and_CPP (C/C++)作者 (noOneKnows)時間12年前 (2013/10/24 22:04), 編輯推噓3(3057)
留言60則, 10人參與, 最新討論串1/1
請問純 C 如何偵測 memcpy 的錯誤呢? 比如說存取到非法的記憶體位址。 謝謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 123.241.67.33


10/24 22:10, , 2F
似乎是無解
10/24 22:10, 2F

10/24 22:14, , 3F
signal handler + longjump?
10/24 22:14, 3F

10/24 22:35, , 4F
我好好研究一下,好像沒有直接的方式
10/24 22:35, 4F

10/24 22:36, , 5F
memcpy 本身好像不會丟 signal 出來
10/24 22:36, 5F

10/24 22:36, , 6F
而且我只要偵測某一段的 memcpy,而不是整個code...
10/24 22:36, 6F

10/24 22:37, , 7F
沒用過 signal 得好好研究,所以這是明路?總之感謝!
10/24 22:37, 7F

10/24 22:41, , 8F
如果你講的是事後偵測而不是當下偵測, 有一個常用的方法
10/24 22:41, 8F

10/24 22:42, , 9F
allocate memory 時前後各多 allocate 1KB, 整塊填滿固定
10/24 22:42, 9F

10/24 22:43, , 10F
pattern, 我喜歡填 ~*^.<*~ 加空白共八 bytes
10/24 22:43, 10F

10/24 22:44, , 11F
然後就很容易看見是否有寫到不該寫的區域
10/24 22:44, 11F

10/24 23:02, , 12F
那讀取呢?
10/24 23:02, 12F

10/24 23:05, , 13F
讀取用 boundary check 比較容易, 也就是在每個讀取時機
10/24 23:05, 13F

10/24 23:05, , 14F
檢查 pointer(address) 是否已經是界外球了...
10/24 23:05, 14F

10/24 23:05, , 15F
GDB不行嗎?
10/24 23:05, 15F

10/24 23:22, , 16F
AddressSanitizer ?
10/24 23:22, 16F

10/25 07:12, , 17F
windows -> SEH?
10/25 07:12, 17F

10/25 08:26, , 18F
因為是要寫給 user 用的,傳進來的是 void *
10/25 08:26, 18F

10/25 08:26, , 19F
請問要怎麼用 boundary check 阿
10/25 08:26, 19F

10/25 10:52, , 20F
存取到非法的記憶體位址不見得會觸發 segfault
10/25 10:52, 20F

10/25 10:52, , 21F
用 signal handler 還是有可能漏網
10/25 10:52, 21F

10/25 10:53, , 22F
如果沒有一定要在程式裡偵測的話就用 valgrind 吧
10/25 10:53, 22F

10/25 22:57, , 23F
唉~需要在程式裡面偵測,看來又是無解的一題
10/25 22:57, 23F

10/25 22:58, , 24F
感謝各位了!!
10/25 22:58, 24F

10/25 22:59, , 25F
傳進指標來的時候沒有要求上層必須一併傳size進來嗎?
10/25 22:59, 25F

10/25 23:00, , 26F
不照size使用記憶體是你的錯,傳進來的size不符是他的錯
10/25 23:00, 26F

10/25 23:01, , 27F
理論上是這樣,但實際上是當在誰那邊誰就要解....
10/25 23:01, 27F

10/25 23:01, , 28F
要做boundary check首先要定義boundary啊...
10/25 23:01, 28F

10/25 23:02, , 29F
你只要證明是對方傳進來的size有誤就可以把問題踢回去
10/25 23:02, 29F

10/25 23:02, , 30F
是阿...不過實務上有難言之隱阿
10/25 23:02, 30F

10/25 23:02, , 31F
不釐清責任歸屬再debug一百年還是無解,程式不是這樣寫滴
10/25 23:02, 31F

10/25 23:03, , 32F
所以要想辦法回傳 error code
10/25 23:03, 32F

10/25 23:05, , 33F
那只有一個可能做法,他allocate的記憶體也是你allocate的
10/25 23:05, 33F

10/25 23:05, , 34F
你自己做記憶體管理才有機會知道boundary在哪
10/25 23:05, 34F

10/25 23:22, , 35F
恩恩感謝,看來是無解了
10/25 23:22, 35F

10/25 23:22, , 36F
前提是你要先確定自己的程式是對的! 所以還是要檢查
10/25 23:22, 36F

10/25 23:50, , 37F
agreen Schottky, 工作有一環是在證明問題出在哪區段 XD
10/25 23:50, 37F

10/26 09:38, , 38F
換C#就知道要怎麼解這問題了
10/26 09:38, 38F

10/26 09:40, , 39F
提供有傳入desc和src size版本的memcpy
10/26 09:40, 39F

10/26 09:40, , 40F
比較size和 copy的長度, 不合法就給個錯誤
10/26 09:40, 40F

10/26 09:41, , 41F
從上面回文來看有點疑惑, 你到底是用純c還是c++??
10/26 09:41, 41F

10/26 09:46, , 42F
C++才有exception, 所以你是用C++?
10/26 09:46, 42F

10/26 12:47, , 43F
有提到 EXCEPTION 嗎
10/26 12:47, 43F

10/26 14:08, , 44F
azureblaze丟的是C++的範例
10/26 14:08, 44F

10/26 14:09, , 45F
SIGSEGV只要是操作非法記憶體就會觸發, 跟memcpy無關吧?
10/26 14:09, 45F

10/26 14:13, , 46F
這問題解法就如同微軟提供memcpy_s, 要求輸入DstSize
10/26 14:13, 46F

10/26 14:15, , 47F
這種情況再出錯就一定是destination和DstSize不匹配
10/26 14:15, 47F

10/26 17:19, , 48F
所以 memcpy 應該是不會主動丟出 SIGSEGV 吧
10/26 17:19, 48F

10/27 00:00, , 49F
在vc下跑memcpy(0,0,1)就會觸發, gcc應該是一樣
10/27 00:00, 49F

10/27 08:21, , 50F
如果傳非 null 指標然後 SIZE 超過呢
10/27 08:21, 50F

10/27 08:21, , 51F
應該就不一定了吧
10/27 08:21, 51F

10/27 11:12, , 52F
這種必須自己檢查, 所以才要user自己傳size資訊
10/27 11:12, 52F

10/27 11:13, , 53F
甚至是將Size資訊和資料綁在一起
10/27 11:13, 53F

10/27 11:14, , 54F
在C++會做成struct去操作, 甚至直接用std::vector存取
10/27 11:14, 54F

10/27 11:26, , 55F
其他語言都會把size資訊保留, 因此很方便, 例如C#
10/27 11:26, 55F

10/27 11:27, , 56F
寫C也可以仿照那種方式來寫啊
10/27 11:27, 56F

10/27 14:56, , 57F
感謝,後來找到解法了,組和混用 sigsetjmp, siglongjmp
10/27 14:56, 57F

10/27 14:57, , 58F
去檢查 adress 再來 memcpy,不過怕太慢我只抽樣調查
10/27 14:57, 58F

10/27 15:18, , 59F
我悟性太低,應該跟 1, 3 樓想表示的做法一樣
10/27 15:18, 59F

10/27 15:19, , 60F
不過或許真有漏洞
10/27 15:19, 60F
文章代碼(AID): #1IQIZxX_ (C_and_CPP)
文章代碼(AID): #1IQIZxX_ (C_and_CPP)