我正试图让Android上的本机崩溃报告工作。我使用breakpad创建转储文件,并使用curl上传它(以与breakpad一起提供的minidump_upload工具非常类似的方式)。
为了测试我试图写入一个解除引用的NULL指针来激发段错误。
在我的转储回调函数中,在成功创建minidump之后从breakpad的信号处理程序调用,我fork()并运行我的上传代码。
设置libCurl工作正常,但随后在curl_easy_perform内部崩溃并发生以下回溯(为了便于阅读而删除了文件名,删除了10以上的帧)。
Program received signal SIGSEGV, Segmentation fault.
0x7356d700 in dprintf_formatf (data=0x7393ba34, stream=0x65, format=0x739458a4 "l>\016", ap_save=...) at .../lib/mprintf.c:518
518 {
(gdb) bt
#0 0x7356d700 in dprintf_formatf (data=0x7393ba34, stream=0x65, format=0x739458a4 "l>\016", ap_save=...) at .../lib/mprintf.c:518
#1 0x7356e5fe in curl_mvsnprintf (buffer=0x73860540 "\b\025\206sa", maxlength=4096, format=0x737a1528 "%s; boundary=%s\r\n", ap_save=...) at .../lib/mprintf.c:932
#2 0x7355d092 in AddFormDataf (formp=0x73861780, size=0x0, fmt=0x737a1528 "%s; boundary=%s\r\n") at .../lib/formdata.c:918
#3 0x7355d606 in Curl_getformdata (data=0x75527970, finalform=0x75511ec0, post=0x75482af0, custom_content_type=0x0, sizep=0x75511ec8) at .../lib/formdata.c:1172
#4 0x73561dfc in Curl_http (conn=0x755300a0, done=0x73861928) at .../lib/http.c:1969
#5 0x7356badc in Curl_do (connp=0x75527978, done=0x73861928) at .../lib/url.c:5897
#6 0x735771f0 in multi_runsingle (multi=0x7551dfa0, now=..., data=0x75527970) at .../lib/multi.c:1218
#7 0x73577aac in curl_multi_perform (multi_handle=0x7551dfa0, running_handles=0x738619cc) at .../lib/multi.c:1714
#8 0x73571fa4 in easy_transfer (multi=0x7551dfa0) at .../lib/easy.c:759
#9 0x7357209a in easy_perform (data=0x75527970, events=false) at .../lib/easy.c:838
#10 0x735720c4 in curl_easy_perform (easy=0x75527970) at .../lib/easy.c:857
让我们分析一下我们在这里得到的东西,它在第3帧开始变得有趣。 这里使用
调用AddFormDataf在第2帧中,一切都很好,构造了va_list(它应该指向两个字符串中的第一个,但我不知道如何在gdb中调试它),并且控制权被移交给vsnprintf, curl内部定义为curl_mvsnprintf。
在第1帧中,所有参数仍然看起来很好,4k缓冲区中有随机数据,但是应该没问题,它会被覆盖,最大长度4096是正确的,格式字符串仍然是我们的格式。创建了nsprintf结构,并将控制权移交给dprintf_formatf - 让我们打印传递给dprintf_formatf的所有参数:
(gdb) print info
$6 = {buffer = 0x73860540 "\b\025\206sa", length = 0, max = 4096}
(gdb) print &info
$7 = (struct nsprintf *) 0x73860510
(gdb) print addbyter
$8 = {int (int, FILE *)} 0x7356e580 <addbyter>
(gdb) print format
$9 = 0x737a1528 "%s; boundary=%s\r\n"
(gdb) print ap_save
$10 = {__ap = 0x73861554}
正如你所看到的,info结构是正确填充的,没有什么可说的关于addbyter函数的函数指针和va_args ap_save,但至少格式字符串仍然可以。
现在,当我们看到第0帧时,一切都被破坏了:
#0 0x7356d700 in dprintf_formatf (data=0x7393ba34, stream=0x65, format=0x739458a4 "l>\016", ap_save=...) at .../curl/./lib/mprintf.c:518
(gdb) print ap_save
$11 = {__ap = 0x739fae60}
信息指针从0x73860510变为0x7393ba34,函数指针从0x7356e580变为0x65,格式字符串从0x737a1528变为0x739458a4,v__list内的__ap从0x73861554变为0x739fae60。
这些(无效的)指针似乎在程序的每次运行中都保持不变 - 每当我运行时,我获得完全相同的数据,流和格式地址,甚至相同的格式内容(“l&gt; \ 016”)该计划。
我有几个问题:
在此先感谢您的帮助,我真的没有想法如何解决这个问题:)