箫天 发表于 2013-3-12 22:20:31

[转]Protel 99 SE 'Format '%x' invalid or... 的分析

(该文为网上搜集)
  之前在笔记本上从来没出现过这个问题, 相同的安装文件. 已经打了protel99seservicepack6的补丁. 换了4核的台式机基本每天都有几次...这个问题在网上搜索, 回答多是不能用太好的机器否则Protel 99 SE 就会有很多问题, 经过分析实际还真是这样的.
Od载入 Client99SE.exe 断点到 Kernel32->RaiseException, 因为这是个delphi未处理异常. 运行进程等待 Client99SE.exe 抛出异常.当调用RaiseException 时查看调用栈定位到函数0DF61357    55                   push    ebp0DF61358    68 9414F60D          push    0DF614940DF6135D    64:FF30              push    dword ptr fs:0DF61360    64:8920              mov     dword ptr fs:, esp0DF61363    C606 00              mov     byte ptr , 00DF61366    E8 CD03E9FF          call    <jmp.&kernel32.GetTickCount>0DF6136B    8BD8                 mov     ebx, eax0DF6136D    8D85 FCFEFFFF        lea     eax, dword ptr 0DF61373    50                   push    eax0DF61374    A1 7CF1F70D          mov     eax, dword ptr 0DF61379    83C0 11              add     eax, 110DF6137C    8985 E4FEFFFF        mov     dword ptr , eax0DF61382    C685 E8FEFFFF 04     mov     byte ptr , 40DF61389    C685 ECFEFFFF 7E     mov     byte ptr , 7E0DF61390    C685 F0FEFFFF 02     mov     byte ptr , 20DF61397    899D F4FEFFFF        mov     dword ptr , ebx0DF6139D    C685 F8FEFFFF 00     mov     byte ptr , 00DF613A4    8D95 E4FEFFFF        lea     edx, dword ptr 0DF613AA    B9 02000000          mov     ecx, 20DF613AF    B8 AC14F60D          mov     eax, 0DF614AC                                 ; ASCII "%s\%s%x.tmp"0DF613B4    E8 0703E9FF          call    <jmp.&Vcl50.Sysutils::Format>0DF613B9    8B95 FCFEFFFF        mov     edx, dword ptr 0DF613BF    8D85 00FFFFFF        lea     eax, dword ptr 0DF613C5    B9 FF000000          mov     ecx, 0FF0DF613CA    E8 71FEE8FF          call    <jmp.&Vcl50.System::LStrToString>0DF613CF    EB 69                jmp     short 0DF6143A0DF613D1    E8 6203E9FF          call    <jmp.&kernel32.GetTickCount>0DF613D6    8BD8                 mov     ebx, eax0DF613D8    8D85 E0FEFFFF        lea     eax, dword ptr 0DF613DE    50                   push    eax0DF613DF    A1 7CF1F70D          mov     eax, dword ptr 0DF613E4    83C0 11              add     eax, 110DF613E7    8985 E4FEFFFF        mov     dword ptr , eax0DF613ED    C685 E8FEFFFF 04     mov     byte ptr , 40DF613F4    C685 ECFEFFFF 7E     mov     byte ptr , 7E0DF613FB    C685 F0FEFFFF 02     mov     byte ptr , 20DF61402    899D F4FEFFFF        mov     dword ptr , ebx0DF61408    C685 F8FEFFFF 00     mov     byte ptr , 00DF6140F    8D95 E4FEFFFF        lea     edx, dword ptr 0DF61415    B9 02000000          mov     ecx, 20DF6141A    B8 C014F60D          mov     eax, 0DF614C0                                 ; ASCII "%s\s%x%.tmp"0DF6141F    E8 9C02E9FF          call    <jmp.&Vcl50.Sysutils::Format>0DF61424    8B95 E0FEFFFF        mov     edx, dword ptr 0DF6142A    8D85 00FFFFFF        lea     eax, dword ptr 0DF61430    B9 FF000000          mov     ecx, 0FF0DF61435    E8 06FEE8FF          call    <jmp.&Vcl50.System::LStrToString>0DF6143A    8D85 DCFEFFFF        lea     eax, dword ptr 0DF61440    8D95 00FFFFFF        lea     edx, dword ptr 0DF61446    E8 EDFDE8FF          call    <jmp.&Vcl50.System::LStrFromString>0DF6144B    8B85 DCFEFFFF        mov     eax, dword ptr 0DF61451    E8 B201E9FF          call    <jmp.&Vcl50.Sysutils::FileExists>0DF61456    84C0                 test    al, al0DF61458  ^ 0F85 73FFFFFF        jnz     0DF613D10DF6145E    8BC6                 mov     eax, esi0DF61460    8D95 00FFFFFF        lea     edx, dword ptr 0DF61466    E8 2DFCE8FF          call    <jmp.&Vcl50.System::PStrCpy>0DF6146B    33C0                 xor     eax, eax0DF6146D    5A                   pop     edx0DF6146E    59                   pop     ecx0DF6146F    59                   pop     ecx0DF61470    64:8910              mov     dword ptr fs:, edx0DF61473    68 9B14F60D          push    0DF6149B0DF61478    8D85 DCFEFFFF        lea     eax, dword ptr 0DF6147E    BA 02000000          mov     edx, 20DF61483    E8 90FDE8FF          call    <jmp.&Vcl50.System::LStrArrayClr>0DF61488    8D85 FCFEFFFF        lea     eax, dword ptr 0DF6148E    E8 7DFDE8FF          call    <jmp.&Vcl50.System::LStrClr>0DF61493    C3                   retn0DF61494  ^ E9 3FFDE8FF          jmp     <jmp.&Vcl50.System::HandleFinally>0DF61499  ^ EB DD                jmp     short 0DF614780DF6149B    5E                   pop     esi0DF6149C    5B                   pop     ebx0DF6149D    8BE5                 mov     esp, ebp0DF6149F    5D                   pop     ebp0DF614A0    C3                   retn堆栈上有一块字符串0013DD1C   0F817B8C  ASCII "C:\PROGRA~1\DESIGN~1\\System\Temp\~35C52FB.tmp"问题出在第二个调用format函数时给予的第一个参数 "%s\s%x%.tmp" 上.用ida插件转换到c代码int __fastcall sub_571334(int a1){  int v1; // esi@1  int v2; // ST04_4@1  DWORD v4; // eax@1  DWORD v5; // eax@2  int v6; // @1  int v7; // @1  int v8; // @1  int v9; // @1  int v10; // @1  char v11; // @1  char v12; // @1  char v13; // @1  DWORD v14; // @1  char v15; // @1  char v16; // @1  v6 = 0;  v7 = 0;  v8 = 0;  v1 = a1;  v2 = *MK_FP(__FS__, 0);  *MK_FP(__FS__, 0) = &v9;  *(_BYTE *)a1 = 0;  v4 = GetTickCount();  v10 = dword_58F17C + 17;  v11 = 4;  v12 = 126;  v13 = 2;  v14 = v4;  v15 = 0;  Sysutils__Format(&str__s__s_x_tmp, &v10, &v8);  System____linkproc___LStrToString(&v16, v8);  while ( 1 )  {    System____linkproc___LStrFromString(&v6, &v16);    if ( !(unsigned __int8)Sysutils__FileExists(v6) )      break;    v5 = GetTickCount();    v10 = dword_58F17C + 17;    v11 = 4;    v12 = 126;    v13 = 2;    v14 = v5;    v15 = 0;
Sysutils__Format(&str__s_s_x__tmp, &v10, &v7);    System____linkproc___LStrToString(&v16, v7);  }  System____linkproc___PStrCpy(v1, &v16);  *MK_FP(__FS__, 0) = v2;  System____linkproc___LStrArrayClr(&v6, 2);  return System____linkproc___LStrClr(&v8);}可以看到这个函数用来完成生成不重复的随机文件名, 当机器太快硬盘太快时GetTickCount返回的值可能在两次调用中相同, 就会调用第二个format发生这个异常 因为Sysutils__Format(&str__s_s_x__tmp, &v10, &v7);处参数是错误的.Ps:我这c盘就一垃圾ssd...只要补丁字符串 "%s\s%x%.tmp" 为 "%s\%s%x.tmp" 就可以了.25735C732578252E746D70 -> 25735C257325782E746D70原来是写 Protel 99 SE 的大神当年没测试到...
  

笨驴熊Rev2.2 发表于 2013-3-12 23:34:47

我的机器貌似一直没有问题,我也是4核心的哇。

八斤 发表于 2013-3-14 23:22:27

用AD的没这问题
页: [1]
查看完整版本: [转]Protel 99 SE 'Format '%x' invalid or... 的分析