分享一个git diff在mac上bug

git diff 在 mac 上有个奇怪现象,有时候我修改了文件,但 git diff 认为它没变;稍作研究后,发现是 mac 和 linux 的 mmap 表现不一致,也不好说是 bug 还是 feature。水一篇文章记录一下。

一、最初的表现

环境:macos 10.15,任意版本的 git 命令。

平时逆向时候会涉及到 section headers 的修复,自己用 C 写代码来修,但发现我修复后的文件无法被 commit,但文件的 hash 确实发生了变化,而且内容也是修改后的内容。

二、测试样例

先使用 c 编写一个简单的使用 mmap 修改文件内容的可执行文件。

然后使用下列命令进行测试

在 macos 上运行,发现 git diff 输出为空;在 linux 上运行,发现 git diff 认为1.bin 被修改了

三、初步结论

偶然使用 ls -la 发现,mac 使用这种方式,文件的修改日期时间戳是不会被刷新的,但 linux 使用这种方式,修改日期时间戳会被刷新。

使用 touch -t 刷新文件的修改日期,就可以让 git diff 感知到文件被修改了。

稍加阅读 git 的代码,大概有类似的行为。因此,初步结论是mac 的锅,mmap 不刷新时间戳,导致 git 抽风。

四、可能性猜测

linux mmap man page 有这句话

The st_ctime and st_mtime field for a file mapped with PROT_WRITE and MAP_SHARED will be updated after a write to the mapped region, and before a subsequent msync(2) with the MS_SYNC or MS_ASYNC flag, if one occurs.

但 mac 没有明确说自己会刷时间,因此这可能是个 feature,也可能是个 bug。

希望有生之年能够看看内核代码实现上有什么区别,以及希望 Lan学弟 能不能帮我破个案。


=============================================================
随着访客的增多,LeadroyaL在本站流量的开支越来越多了,曾经1元能用1个月,现在1元只能用3天。如果觉得本文帮到了你,希望能够为服务器的流量稍微打赏一点,谢谢!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code