Malloc打破了Serenity的JPGLoader,或者:如何赢得彩票

2021-06-03 23:33:05

我有机会在本周调查Serenityos的一个有趣的错误。它与操作系统中的JPG图像解码有关。出于某种原因,当jpg图像浏览时,它会如此:

奇怪,呵呵?似乎是RGB与BGR的简单混淆。并熟悉,在jpgloader.cpp上进行以下更改:

- const颜色{(u8)block.y [pixel_index],(u8)block.cb [pixel_index],(u8)block.cr [pixel_index]}; + const颜色{(u8)block.cr [pixel_index],(u8)block.cb [pixel_index],(u8)block.y [pixel_index]}; context.bitmap-> set_pixel(x,y,颜色);

Git将在一个月前报告最后一个非恢复的changeto jpgloader.cpp:

而且我记得JPG的图像在一周或两只星期内工作得很好,因为我已经将JPG图像设置为我的背景,如果它看起来会注意到。

好吧,时间达成一分!我不知道何时开始,所以我选择了最后1000个组合(其中图像正确地显示了),并开始了Boting。

如果您想避免C ++抱怨,请跳到下一节。

Serenityos是一个专注于做其所有权的操作系统项目,也有自己的标准库,称为AK(代表不可知论者)。这库是类似的TOC ++的STL,但由于不必支持无数的无数而更具可读性操作系统而不必争论自己符合丑陋的编码标准。

有一个关于在相同的存储库中拥有标准库的很好的东西,它的用户是制作变化非常简单,因为更改传播到从主人那里拉动。然而,这是一个双刃剑,当时是C ++;因为每个人都包括标准库(即使您没有包含它,您的包含遗嘱),而且因为C ++的模板系统意味着模板所必须在标题中包含定义的所有内容,这意味着随时有人触摸AAK在提交中,必须重建整个操作系统(写入时〜3400个文件)。 CCache,虽然在许多情况下有用,但不能处理这种情况。由于Serenityos项目的Breakneck节奏,因此每100个提交左右,某人会触摸AK。

因此,在1000个提交期间,我最终开始了,我必须在2011年划痕上从划痕到3-5次与沙质桥接电脑上的4-5次。虽然这不是项目的错,但我仍然很生气。

所以,在Bisecting 1000的提交后,从头开始重建操作系统,几次拉出我的发发,因为我不明白是如何工作的,我终于找到了破坏JPG图像的提交。 Drumroll请...

F89E8FB71A4893911EE5125F34BD5BBB99327D33AUTHOR:GUNNAR BEUTNERAUTHORDATE:5月15日10:06:41 2021 + 0200AK + LIBC:实现Malloc_Good_size()并将其用于向量/ hashtableThis实现accos api malloc_good_size()返回给定请求的分配大小的返回thetrue分配大小的macos api malloc_good_size()。这使我们可以使用Malloc Chunk中的所有可用内存。对于35字节的Malloc请求,我们的Malloc可能是大小64的块,但剩下的29个字节将未使用。固定真正的分配大小允许我们要要求更浪费的USAbleMemory,以浪费并使未来可用的前视,哈希表和可能其他呼叫者。

与其他开发人员的初步讨论让我认为JPGLoaderOror expe of the Chain的东西取决于向量和直接进入它时的容量。所以我开始狩猎令人沮丧的原因。

提交似乎触摸了两个主要的容器类型:Hashtable(哪个HashMap取决于)和向量。两者都用于JPGLoader代码,也可能是这里问题的原因。

new_capacity = max(new_capacity,static_cast< size_t>(4)); - new_capacity = kmalloc_good_size(new_capacity * sizeof(桶))/ sizeof(桶);自动* old_buckets = m_buckets;

并重建系统,同时在聊天时开玩笑,关于这是如何无法解的问题。

什么?如何?为什么哈希表的能力是不同的?! Hashtableis甚至不是您可以写入的连续数据流,所以你也不应该能够承担其容量!

在我向您展示完整故事之前,我将为JPGLoader如何运作,我会简要介绍一个简短的背景。

JPGLoader先前会将JPG组件的信息从JPG文件的“开始”部分中的JPG组件读取为名为Component的结构,并在Hashtable中存储。当然,每款Comonent的JPG文件中的顺序应该始终是y,cb和cr,因此组件结构普通同步携带serial_id,这是文件的位置。组件在哈希表中的原因是它们会在“扫描开始”部分中的组件排序时会检查它们,以确保SOS部分中的所有组件都处于预期的顺序中。为什么通过线性地迭代组件来写入这种代码,而不是刚刚检查Actid,而不是攻击对方,我不知道。

无论如何,在JPGLoader的不同分段期间,这些组件将在JPGLoader的不同分段期间迭代,在此期间组件信息将被禁用以在宏块上执行变换。

当我添加了一些调试打印时,看看如何阅读组件,我在your back的comput中看到它:

imagedecoder(33:33):查看组件0imagedecoder(33:33):查看组件2imagedeCoder(33:33):查看组件1ImagedeCoder(33:33):查看组件0imagedEcoder(33:33):查看组件2imagedecoder(33:33):看成分1 ...

imagedecoder(33:33):查看组件0imagedeCoder(33:33):查看组件1ImagedeCoder(33:33):查看组件2imagedeCoder(33:33):查看组件0imagedeCoder(33:33):查看组件1imagedecoder(33:33):看组件2 ...

这个拼图的最后一块:在我的机智结束时用Cxbyte讨论这个错误,我们在营造上搞乱了组件的顺序,以查看会发生什么,Andgot此消息:

有人使用哈希特可以存储应订购的对象,然后使用基本的Hashtable迭代器

JPG文件中的组件ID的哈希传递给INT_HASHFOR哈希表桶选择

他们不仅仅是为了秩序的正确价值,他们只需正确的铲斗就可以了解一个哈希表即可正确的订单

这导致霍夫曼流以正确的顺序读取每种群体,从而掩盖错误

自从JPGLoader的开始以纯粹的运气直到适合哈希表的大小,因此这个错误被屏蔽

最后,在大约10个小时的调试结束时,这里是ThecImmitthat修复了这个错误的这个怪物:

a10ad24c760bfe713f1493e49dff7da16d14bf39author:sin-ackauthordate:mon 5月31日15:22:04 2021 + 0000commit:linus grohcommitdate:5月31日星期一17:26:11 2021 + 0100libgfx:make jpgloader迭代组件确定isticalyjpgloader用于存储哈希表中的组件信息,索引索引的ind由JPEG文件分配。对于大多数目的而言,这很好,但在F89E8FB7之后,这被揭示为缺陷的实现,这导致非确定性迭代在组件上。此问题先前被INT_HASH的完美风暴掩盖了整数0,1和2的完美风暴; AK :: Hashtable拥有正确数量的桶,用于使用INT_HASH散列正确的组件。但是,在F89E8FB7之后,Malloc_Good_size用于确定空间丢弃量;这导致组件的排序变为改变,启动与红色和蓝色通道的逆转开始。在随机调整组件的顺序后,最终被确定为不一致的订单导致霍夫曼解码失败。这是大约10小时的毛发拉动,由于触摸Ak.Gunnar之间的提交之间的Botiting而重复的全面重建。我喜欢你,但请不要让我再次经历这一点。 :^)对Andrew Kaster,BGIANF,CxByte和Gunnar的信用,为DebuggingHelp。

有时最简单的问题可能会在巨大的错误中指出。我可以通过刚刚交换正确的参数的顺序然后左右,我可以保护这个问题;直到别人来到别人并再次改变了这方面。值得庆幸的是,我们将能够在和平中使用正确的彩色查看守基地。

感谢Cxbyte,Gunnar,Andrew和Brian,为他们的帮助调试,他们的乐于助人的提示。特别是Gunnar尤其是发现这个错误的人,尽管我的讽刺Jab在提交消息中有助于揭示这种非常有趣的错误,所以他是一个可能成为这篇帖子的人。

另外,感谢介绍这个错误的人(提交日志得到了一个有点措施,所以我不确定谁做了,希望他能买一张彩票。 :^)

并感谢您的阅读。我可能会在未来的某个时间发布,但工作让我忙碌。但也许我会发现另一个臭虫吸入一个rabbithole。敬请关注!