STL字符串assign函数崩溃:寄存器值异常变更排查求助
问题场景
进程运行在VMware虚拟机的Windows Server 2008 R2系统中,仅单线程执行,崩溃发生在STL的std::basic_string<wchar_t>::assign函数内联的std::_WChar_traits::assign逻辑中,触发指令为:
000000013f1f2705 66890433 mov word ptr [rbx+rsi],ax
此时寄存器上下文显示rbx=0、rsi=0,导致访问0x00000000地址触发违规。
寄存器与指令上下文
崩溃时寄存器状态
rax=0000000000000000 rbx=0000000000000000 rcx=000000013f2c96e0 rdx=000000013f344924 rsi=0000000000000000 rdi=00000000002df498 rip=000000013f1f2705 rsp=00000000002df350 rbp=00000000002df489 r8=0000000000000000 r9=000000013f1d0000 r10=000000013f344924 r11=0000000000000000 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei pl zr na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
崩溃指令的上下文代码
00000001`3f1f26ed 488d1c12 lea rbx,[rdx+rdx] 00000001`3f1f26f1 48895110 mov qword ptr [rcx+10h],rdx 00000001`3f1f26f5 4c8bc3 mov r8,rbx 00000001`3f1f26f8 498bd1 mov rdx,r9 00000001`3f1f26fb 488bce mov rcx,rsi 00000001`3f1f26fe e80d6f0d00 call XXXXX!memcpy (00000001`3f2c9610) 00000001`3f1f2703 33c0 xor eax,eax 00000001`3f1f2705 66890433 mov word ptr [rbx+rsi],ax
核心问题分析
你确认memcpy未修改rsi,但当前rsi为0,可能的原因包括:
rsi初始值即为0:调用memcpy前的
mov rcx,rsi将rsi作为memcpy的目标地址参数。如果此时rsi已经是0,且memcpy的长度参数r8=rbx=0(由lea rbx,[rdx+rdx]计算而来,若源字符串长度为0则rbx为0),memcpy会因长度为0直接返回,不会触发崩溃,但后续执行mov word ptr [rbx+rsi],ax时,就会访问0x00000000地址。这种情况说明代码在处理空字符串的assign时存在逻辑漏洞。basic_string对象内部状态损坏:
rcx是当前basic_string对象的地址,mov qword ptr [rcx+10h],rdx是将源字符串指针写入对象的某个成员。如果该字符串对象的内部结构(如缓冲区指针、长度、容量字段)已被之前的操作破坏,会导致后续逻辑错误地使用空指针作为目标缓冲区。源字符串有效性异常:
rdx指向的源字符串可能无效,或者长度计算错误。比如源字符串并非合法的以\0结尾的wchar_t字符串,导致lea rbx,[rdx+rdx]计算出的长度为0,同时目标缓冲区的偏移/指针rsi为空,最终触发空地址访问。编译器优化导致的逻辑偏差:由于assign函数被内联优化,编译器可能调整了寄存器的使用逻辑,使得rsi的用途与预期不符。即使memcpy未修改rsi,进入这段代码时rsi就已被设置为0,而代码逻辑错误地假设它指向有效的目标缓冲区位置。
排查建议
- 检查
rcx指向的basic_string对象的内存布局,查看其缓冲区指针、长度、容量等核心字段的值,确认对象是否处于有效状态。 - 验证
rdx指向的源字符串内容,确认其是否为空字符串,以及长度计算是否正确(比如是否存在正确的终止符)。 - 查看该assign函数的完整反汇编或对应源码,明确rsi的具体用途:是目标缓冲区的偏移量,还是目标缓冲区的指针?如果是指针,rsi为空说明目标缓冲区未被正确分配。
- 排查是否存在内存破坏问题:比如之前的操作越界写入,破坏了basic_string对象的内部数据或堆内存结构。
内容的提问来源于stack exchange,提问作者Frank

