Укажите отработанное время

Отработанное время:
Продуктивное время:
Bug 806 - Падает wine при попытке сохранить batch-файл.   Make a simular bug
Summary: Падает wine при попытке сохранить batch-файл.
Status: CLOSED FIXED
Alias: None
Product: WINE@Etersoft
Classification: Продукты (Products)
Component: Общее (show other bugs)
Version: 1.0.7
Hardware: PC Linux
: P5 normal
Target Milestone: ---
Assignee: BUGS@Etersoft
QA Contact:
URL:
Whiteboard:
Keywords:
: 952 (view as bug list)
Depends on: 447 952
Blocks: 450 1838 8500
  Show dependency treegraph
 
In work:
Reported: 2007-10-22 19:30 MSD by Sergey Lebedev
Modified: 2012-12-15 16:34 MSK (History)
5 users (show)

See Also:
Заявки RT:
Связано с:
Дата напоминания:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sergey Lebedev 2007-10-22 19:30:06 MSD
После открытия Fine Reader 8.0, нажать Save as batch.. Ввести любой символ.
В консоле следующее
wine: Unhandled page fault on write access to 0x00000000 at address 0x711c7279 (thread 0009), starting debugger...
WineDbg starting on pid 0008
Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x711c7279).
Register dump:
 CS:0073 SS:007b DS:007b ES:007b FS:003b GS:0033
 EIP:711c7279 ESP:7fd4f318 EBP:7fd4f330 EFLAGS:00210202(   - 00      - -RI1)
 EAX:7ff6ff38 EBX:00000000 ECX:00000000 EDX:7116ff58
 ESI:7fd4f590 EDI:00000001
Stack dump:
0x7fd4f318:  7ff85a38 7f66d638 7ff858f8 7ff858f8
0x7fd4f328:  00000000 7ff858fc 7fd4f5a0 7f5fea2f
0x7fd4f338:  7ff6ff38 00000001 7fd4f590 00000000
0x7fd4f348:  00000111 00009fb6 00000000 00000000
0x7fd4f358:  00000000 7fd4f37e 00020054 00000000
0x7fd4f368:  00000000 7bd8fb60 7f9bbefc 00000001
Backtrace:
=>1 0x711c7279 in browseui (+0x67279) (0x7fd4f330)
  2 0x7f5fea2f in shell32 (+0xea2f) (0x7fd4f5a0)
  3 0x7f996cca WINPROC_wrapper+0x1a() in user32 (0x7fd4f5d0)
  4 0x7f99746e in user32 (+0xa746e) (0x7fd4f610)
  5 0x7f99c943 CallWindowProcW+0x53() in user32 (0x7fd4f650)
  6 0x7f9637eb DispatchMessageW+0x15b() in user32 (0x7fd4f690)
  7 0x7f931acb IsDialogMessageW+0xfb() in user32 (0x7fd4f7f0)

  8 0x2386564f in awl (+0x6564f) (0x7fd4f868)
  9 0x2382ce57 in awl (+0x2ce57) (0x00000001)
  10 0x00000000 (0x00000000)
0x711c7279: movl        %ecx,0x0(%ebx)
Comment 1 Константин Кондратюк 2007-10-23 09:39:16 MSD
Очень похоже на 447. Думаю, причины одни и те же.
Comment 2 Анатолий Лютин 2008-05-21 19:52:16 MSD
90% - август
Comment 3 Анатолий Лютин 2008-05-23 13:09:38 MSD
Не всегда воспроизводится.
Comment 4 Анатолий Лютин 2008-07-10 15:13:34 MSD
Не занимаюсь.
Comment 5 Anton Rudnev 2008-08-18 15:00:16 MSD
Баг возникает не всегда.
После того как File -> Save as batch..., вводишь любое имя, нажимаешь на кнопку Save, в консоле появляется ошибка с примерно следующим бэктрейсом (каждый раз немного разный):
Backtrace:
=>1 0x011ae8a9 (0x0032fcd8)
  2 0x2382cbe1 in awl (+0x2cbe1) (0x0032fd04)
  3 0x2382cea3 in awl (+0x2cea3) (0x00000000)

Если тестировать несколько раз, то строка 1 в бэктрейсе обычно всегда разная. Зато строки
  2 0x2382cbe1 in awl (+0x2cbe1) (0x0032fd04)
  3 0x2382cea3 in awl (+0x2cea3) (0x00000000)
с каждым разом всегда одинаковы.
----------------------------------------------------------------------

Дизассемблируем Awl.dll (находится в c:\Program Files\ABBY ... Reader, или куда поставишь)
Адрес 0x2382cbe1 соответствует вызову 
         ...
.text:2382CBDE    call    dword ptr [eax+8] ;падает
.text:2382CBE1    mov     ecx, [ebp+var_C] ;2 строчка в бэктрейсе
         ...
Этот участок кода представляет из себя кусок функции CMessageLoop::TryOnIdle(long). Вот она полностью:

.text:2382CBB0 ; protected: bool __thiscall AWL::CMessageLoop::TryOnIdle(long)
.text:2382CBB0                 public ?TryOnIdle@CMessageLoop@AWL@@IAE_NJ@Z
.text:2382CBB0 ?TryOnIdle@CMessageLoop@AWL@@IAE_NJ@Z proc near
.text:2382CBB0
.text:2382CBB0 var_10          = dword ptr -10h
.text:2382CBB0 var_C           = dword ptr -0Ch
.text:2382CBB0 var_4           = dword ptr -4
.text:2382CBB0 arg_0           = dword ptr  8
.text:2382CBB0
.text:2382CBB0                 push    ebp
.text:2382CBB1                 mov     ebp, esp
.text:2382CBB3                 push    0FFFFFFFFh
.text:2382CBB5                 push    offset loc_2387DD50
.text:2382CBBA                 mov     eax, large fs:0
.text:2382CBC0                 push    eax
.text:2382CBC1                 mov     large fs:0, esp
.text:2382CBC8                 sub     esp, 8
.text:2382CBCB                 mov     edx, [ebp+arg_0]
.text:2382CBCE                 mov     eax, [ecx]      ; первый адрес из объекта
.text:2382CBD0                 push    ebx
.text:2382CBD1                 push    esi
.text:2382CBD2                 push    edi
.text:2382CBD3                 mov     [ebp+var_10], esp
.text:2382CBD6                 push    edx
.text:2382CBD7                 mov     [ebp+var_4], 0
.text:2382CBDE                 call    dword ptr [eax+8] ; передается управление в рандомную область
.text:2382CBE1                 mov     ecx, [ebp+var_C] ; (2) в бэктрейсе
.text:2382CBE4                 mov     large fs:0, ecx
.text:2382CBEB                 pop     edi
.text:2382CBEC                 pop     esi
.text:2382CBED                 pop     ebx
.text:2382CBEE                 mov     esp, ebp
.text:2382CBF0                 pop     ebp
.text:2382CBF1                 retn    4
.text:2382CBF1 ?TryOnIdle@CMessageLoop@AWL@@IAE_NJ@Z endp

таким образом получается, что по адресу dword ptr [eax+8] должна находится некоторая, успешно отрабатывающая функция. Но получается, что туда помещается указатель куда-то не туда.
Очень похоже, что dword ptr [eax+8], это третье поле какой-то структуры указатель на которую находится в eax.
Смотрим, что меняет eax перед этим:
        ...
.text:2382CBCE                 mov     eax, [ecx]
        ...
В еax сваливается что-то, что находится по адресу, на который указывает ecx. И перед этим ecx ничего не меняет.

Смотрим, на первую строчку
.text:2382CBB0 ; protected: bool __thiscall AWL::CMessageLoop::TryOnIdle(long)
        ...
из нее видим, что вызов CMessageLoop::TryOnIdle(long) придерживается конвенции thiscall (о конвенциях можно почитать по ссылке http://en.wikibooks.org/wiki/Reverse_Engineering/Calling_Conventions )
Согласно конвенции thiscall, перед вызовом метода объекта в ecx заносится указатель на него. Значит в ecx находится указатель на объект класса CMessageLoop...



Comment 6 Anton Rudnev 2008-08-18 15:39:35 MSD
... далее обращаемся к 3-й строчке бэктрейса:
  3 0x2382cea3 in awl (+0x2cea3) (0x00000000)

Смотрим, что находится по адресу 0x2382cea3 в дизассемблированном Awl.dll:
         ...
.text:2382CE9E  call    ?TryOnIdle@CMessageLoop@AWL@@IAE_NJ@Z ; AWL::CMessageLoop::TryOnIdle(long)
.text:2382CEA3                 inc     ebp             ; (3) в бэктрейсе
         ...

Этот участок кода принадлежит функции CMessageLoop::DoMessageLoop(void), вот ее код полностью:

.text:2382CE10 ; public: void __thiscall AWL::CMessageLoop::DoMessageLoop(void)
.text:2382CE10                 public ?DoMessageLoop@CMessageLoop@AWL@@QAEXXZ

.text:2382CE10 var_24          = dword ptr -24h
.text:2382CE10 var_14          = dword ptr -14h
.text:2382CE10 var_C           = dword ptr -0Ch
.text:2382CE10 var_4           = dword ptr -4
.text:2382CE10
.text:2382CE10                 push    0FFFFFFFFh
.text:2382CE12                 push    offset loc_2387DD78
.text:2382CE17                 mov     eax, large fs:0
.text:2382CE1D                 push    eax
.text:2382CE1E                 mov     large fs:0, esp
.text:2382CE25                 sub     esp, 8
.text:2382CE28                 push    ebx
.text:2382CE29                 push    ebp
.text:2382CE2A                 push    esi
.text:2382CE2B                 push    edi
.text:2382CE2C                 mov     esi, ecx
.text:2382CE2E                 push    esi
.text:2382CE2F                 lea     eax, [esi+4]
.text:2382CE32                 push    eax
.text:2382CE33                 push    offset ?currentMessageLoop@CMessageLoop@AWL@@1PAV12@A ; AWL::CMessageLoop * AWL::CMessageLoop::currentMessageLoop
.text:2382CE38                 lea     ecx, [esp+30h+var_14]
.text:2382CE3C                 call    sub_2382C960
.text:2382CE41                 xor     ebp, ebp
.text:2382CE43                 mov     [esp+24h+var_4], ebp
.text:2382CE47                 mov     bl, 1
.text:2382CE49                 lea     esp, [esp+0]
.text:2382CE50
.text:2382CE50 loc_2382CE50:
.text:2382CE50                 mov     ecx, esi
.text:2382CE52                 call    ?PumpMessage@CMessageLoop@AWL@@IAE_NXZ ; AWL::CMessageLoop::PumpMessage(void)
.text:2382CE57                 test    al, al
.text:2382CE59                 jz      short loc_2382CEAC
.text:2382CE5B                 lea     edi, [esi+8]
.text:2382CE5E                 push    edi
.text:2382CE5F                 mov     ecx, esi
.text:2382CE61                 call    ?TryIsIdleMessage@CMessageLoop@AWL@@IAE_NAAUtagMSG@@@Z ; AWL::CMessageLoop::TryIsIdleMessage(tagMSG &)
.text:2382CE66                 test    al, al
.text:2382CE68                 jz      short loc_2382CE6E
.text:2382CE6A                 mov     bl, 1
.text:2382CE6C                 xor     ebp, ebp
.text:2382CE6E
.text:2382CE6E loc_2382CE6E:
.text:2382CE6E                 push    0
.text:2382CE70                 push    0
.text:2382CE72                 push    0
.text:2382CE74                 push    0
.text:2382CE76                 push    edi
.text:2382CE77                 call    off_238E11D0
.text:2382CE7D                 test    eax, eax
.text:2382CE7F                 jnz     short loc_2382CE50
.text:2382CE81                 test    bl, bl
.text:2382CE83                 jz      short loc_2382CE50
.text:2382CE85                 lea     edi, [esi+8]
.text:2382CE88
.text:2382CE88 loc_2382CE88:
.text:2382CE88                 push    0
.text:2382CE8A                 push    0
.text:2382CE8C                 push    0
.text:2382CE8E                 push    0
.text:2382CE90                 push    edi
.text:2382CE91                 call    off_238E11D0; PeekMessageW(edi,0,0,0,0)
.text:2382CE97                 test    eax, eax
.text:2382CE99                 jnz     short loc_2382CE50
.text:2382CE9B                 push    ebp
.text:2382CE9C                 mov     ecx, esi
.text:2382CE9E                 call    ?TryOnIdle@CMessageLoop@AWL@@IAE_NJ@Z ; AWL::CMessageLoop::TryOnIdle(long)
.text:2382CEA3                 inc     ebp; (3) в бэктрейсе
.text:2382CEA4                 test    al, al
.text:2382CEA6                 jnz     short loc_2382CE88
.text:2382CEA8                 xor     bl, bl
.text:2382CEAA                 jmp     short loc_2382CE50
.text:2382CEAC loc_2382CEAC: 
.text:2382CEAC                 lea     ecx, [esp+24h+var_14]
.text:2382CEB0                 call    sub_2382C980
.text:2382CEB5                 mov     ecx, [esp+24h+var_C]
.text:2382CEB9                 pop     edi
.text:2382CEBA                 pop     esi
.text:2382CEBB                 pop     ebp
.text:2382CEBC                 pop     ebx
.text:2382CEBD                 mov     large fs:0, ecx
.text:2382CEC4                 add     esp, 14h
.text:2382CEC7                 retn
.text:2382CEC7 ?DoMessageLoop@CMessageLoop@AWL@@QAEXXZ endp
------------------------------------------------------------------------

Перед вызовом вызовом CMessageLoop::TryOnIdle(long) указатель на объект CMessageLoop заносится из esi, а единственный long-аргумент поднимается в стек из ebp (т. е. в псевдокоде esi->TryOnIdle(ebp) ):
.text:2382CE9B                 push    ebp
.text:2382CE9C                 mov     ecx, esi

Строчки 
.text:2382CE97                 test    eax, eax
.text:2382CE99                 jnz     short loc_2382CE50
можно понять как if(eax != 0) goto loc_382CE50 /* очевидно переход на начало цикла */

Последовательность
.text:2382CE88                 push    0
.text:2382CE8A                 push    0
.text:2382CE8C                 push    0
.text:2382CE8E                 push    0
.text:2382CE90                 push    edi
.text:2382CE91                 call    off_238E11D0
означает ни что иное как PeekMessageW(edi, 0, 0, 0, 0), поскольку по адресу off_238E11D0 находится указатель на блок кода:
.text:23879D79 sub_23879D79    proc near
.text:23879D79                 push    offset loc_2387AA05 ; Value
.text:23879D7E                 push    dword_238E22FC  ; int
.text:23879D84                 push    offset off_238E11D0 ; Target
.text:23879D89                 push    offset aPeekmessagew ; "PeekMessageW"
.text:23879D8E                 push    offset aUser32_dll_0 ; "user32.dll"
.text:23879D93                 call    sub_2387A74A
.text:23879D98                 jmp     off_238E11D0
.text:23879D98 sub_23879D79    endp
который (упрощенно) вызовом call sub_2387A74A через loadLibrary и GetProcAddr получает адрес на PeekMessageW и передает туда часть стека с параметрами от PeekMessageW (которые заносятся в стек в DoMessageLoop)...
Comment 7 Anton Rudnev 2008-08-18 16:15:34 MSD
Возможно дело не в PeekMessageW, но есть одна догадка...

Функция BOOL WINAPI PeekMessageW( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT flags ) ловит сообщения из очереди сообщений.
Кроме того, что она возвращает TRUE/FALSE (пришло/не пришло сообщение в очередь), она еще и в случае TRUE модифицирует переданную в первом аргументе структуру MSG *msg_out. Эта структура отражает содержимое пойманного сообщения. Вот она:
typedef struct tagMSG{
    HWND    hwnd;          // окошко
    UINT    message;       // код сообщения
    WPARAM  wParam;        // wParam специфичный данному сообщению 
    LPARAM    lParam;      // lParam специфичный данному сообщению
    DWORD     time;        // идентификатор времени
    POINT   pt;            // координаты мышиного курсора
} MSG, *PMSG, *LPMSG;

Каждый раз, перед тем как wine рушится, функция PeekMessageW вызывается в цикле 32 раза (обнаружено через дебаглог). Среди тех случаев, когда она ловит какое-либо сообщение, появляется сообщение с кодом message=0x113, что есть сообщение WM_TIMER. Для него следующие специфичные: wParam - идентификатор времени, lParam - типа (TIMERPROC *) - указатель на заданную пользователем функцию void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) (см. http://msdn.microsoft.com/en-us/library/aa932778.aspx )

Возможно приводящий к ошибке call dword offset [eax + 8] есть как раз вызов по lParam из MSG, который неправильно установлен через SetTimer (см. http://msdn.microsoft.com/en-us/library/ms644906(VS.85).aspx )

отрабатываю пока эту версию.
Comment 8 Anton Rudnev 2008-08-19 16:03:41 MSD
это не MSG где третьим элементом является функция, и вот почему...

Рассмотрим в методе CMessageLoop::TryOnIdle(long) следующие строчки:

... ... ecx содержит ссылку на объект CMessageLoop ...
... ... регистр ecx нигде не меняется ... ...
.text:2382CBCE                 mov     eax, [ecx] ; в eax кладется первое поле из объекта CMessageLoop
... ... eax нигде не меняется
.text:2382CBDE                 call    dword ptr [eax+8] ; вызов, который падает
... ... следующая строчка заночится в бэктрейс

По на форуме васма ( http://www.wasm.ru/forum/viewtopic.php?id=28409 ) подсказывают, что первое поле объекта вообще-то говоря ссылка на таблицу виртуальных функций.

Очевидно предположить, что первое поле инициализируется в конструкторе . Вот полный код CMessageLoop::CMessageLoop(void):
.text:2382CA80 ; public: __thiscall AWL::CMessageLoop::CMessageLoop(void)
.text:2382CA80                 xor     eax, eax
.text:2382CA82                 push    esi
.text:2382CA83                 mov     esi, ecx
.text:2382CA85                 push    eax
.text:2382CA86                 push    eax
.text:2382CA87                 lea     ecx, [esi+28h]
.text:2382CA8A                 mov     dword ptr [esi], offset ??_7CMessageLoop@AWL@@6B@ ; const AWL::CMessageLoop::`vftable'
.text:2382CA90                 mov     [esi+4], eax
.text:2382CA93                 mov     [esi+24h], eax
.text:2382CA96                 call    ds:??0CPoint@FObj@@QAE@HH@Z ; FObj::CPoint::CPoint(int,int)
.text:2382CA9C                 mov     eax, esi
.text:2382CA9E                 pop     esi
.text:2382CA9F                 retn
.text:2382CA9F ??0CMessageLoop@AWL@@QAE@XZ endp

После строчки .text:2382CA83 mov esi, ecx, указатель на объект попадает в esi.
В строчке .text:2382CA8A  mov dword ptr [esi], offset ??_7CMessageLoop@AWL@@6B@ ; const AWL::CMessageLoop::`vftable', происходит инициализация таблицы витруальных функций.

Заглянем в таблицу виртуальных функций по смещению offset ??_7CMessageLoop@AWL@@6B@ и увидим следующую таблицу:
.rdata:23889F60 ;const AWL::CMessageLoop::`vftable'
.rdata:23889F60 ??_7CMessageLoop@AWL@@6B@ dd offset ?PreTranslateMessage@CMessageLoop@AWL@@UAE_NAAUtagMSG@@@Z
.rdata:23889F60 ;DATA XREF: AWL::CMessageLoop::CMessageLoop(void)+Ao
.rdata:23889F60 ;AWL::CMessageLoop::~CMessageLoop(void)o ...
.rdata:23889F60 ;AWL::CMessageLoop::PreTranslateMessage(tagMSG &)

.rdata:23889F64  dd offset ?IsIdleMessage@CMessageLoop@AWL@@UAE_NAAUtagMSG@@@Z 
                ;AWL::CMessageLoop::IsIdleMessage(tagMSG &)
.rdata:23889F68  dd offset ?OnIdle@CMessageLoop@AWL@@UAE_NJ@Z 
                ;AWL::CMessageLoop::OnIdle(long)
.rdata:23889F6C  dd offset ?ValidateData@CWindow@AWL@@MAE_NXZ 
                ;AWL::CWindow::ValidateData(void)
.rdata:23889F70  dd offset ?OnQuit@CMessageLoop@AWL@@UAEXH@Z 
                ;AWL::CMessageLoop::OnQuit(int)
.rdata:23889F74  dd offset ?UpdateControls@CDialog@AWL@@EAE_NXZ 
                ;AWL::CDialog::UpdateControls(void)

[eax + 8] в CMessageLoop::OnIdle соответствует, 3-му элементу в этой таблице.
Т. е. call dword ptr [eax + 8] есть вызов AWL::CWindow::ValidateData(void).

Вот ее код:
.text:2380B8E0 ; protected: virtual bool __thiscall AWL::CWindow::ValidateData(void)
.text:2380B8E0                 public ?ValidateData@CWindow@AWL@@MAE_NXZ
.text:2380B8E0 ?ValidateData@CWindow@AWL@@MAE_NXZ proc near
.text:2380B8E0                 mov     al, 1           ; bool __cdecl 
.text:2380B8E2                 retn
.text:2380B8E2 ?ValidateData@CWindow@AWL@@MAE_NXZ endp

Очевидно, что внутри это функции падать ничего не может, она просто возвращает TRUE.

Есть догадка о том, что что-то нарушает таблицу виртуальных функций, тем самым вызывается не CWindow::ValidateData, а что-то по ошибочному адресу...
Comment 9 Константин Кондратюк 2008-12-04 13:35:22 MSK
*** Bug 952 has been marked as a duplicate of this bug. ***
Comment 10 Vitaly Lipatov 2012-01-18 03:09:17 MSK
Откладываем, bugs@ в ближайшее время делать ничего не будет.
Comment 11 Vitaly Lipatov 2012-12-15 16:34:10 MSK
На wine-etersoft 2.0.3 отлично работет Fine Reader 8.0, всё сохраняется и не падает. Закрываю.