Summary: | написать тест для функции BITMAP_SetOwnerDC | ||
---|---|---|---|
Product: | WINE@Etersoft | Reporter: | Виталий Перов <vitperov> |
Component: | Графика GDI / DIB / GDIPLUS | Assignee: | Sergei Novosyolov <chi> |
Status: | CLOSED INVALID | QA Contact: | |
Severity: | minor | ||
Priority: | P5 | CC: | 1c, lav, vostok |
Version: | unspecified | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | Linux | ||
Whiteboard: | |||
Заявки RT: | Связано с: | ||
Дата напоминания: | |||
Bug Depends on: | |||
Bug Blocks: | 1689, 7389 |
Description
Виталий Перов
2008-06-07 19:13:54 MSD
В ходе написания нужного теста был получен случай, когда wine однозначно и постоянно падает. Это происходит в функции SetDIBits на вызове dc->funcs->pSetDIBits: if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done; result = lines; if (bitmap->funcs) { if (bitmap->funcs != dc->funcs) ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc ); else if (dc->funcs->pSetDIBits) { result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines, bits, info, coloruse ); } } wine: Unhandled page fault on read access to 0x00000000 at address 0x7e91365b (thread 0009), starting debugger... В WINDOWS тест проходит нормально. Если я правильно понял, то падает на: result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines, bits, info, coloruse ); А функции точно передаются не нулевые параметры? Я думаю, что в первую очередь надо проверить - заполняется ли указатель pSetDIBits, затем - указатель dc->funcs и только затем dc и нулевые параметры. Имеется ввиду - pSetDIBits - действительно ли необходимая функция... По dc->physDev так же возможны падения - я наталкивался пару раз, когда physDev заполнялся только NULL. В результате проверки получилось: dc = 0x0011bd30 dc->funcs = 0x001183b0 dc->funcs->pSetDIBits = 0x7e91c7b0 Из переданных в функцию параметров, некоторые действительно имели нулевое значение: dc->physDev = 0x0011bf00 hbitmap = 0x000001d4 startscan = 0x00000000 lines = 0x00000064 bits = 0x00000000 info = 0x00000000 coloruse = 0x00000000 (In reply to comment #6) > В результате проверки получилось: > > dc = 0x0011bd30 > dc->funcs = 0x001183b0 > dc->funcs->pSetDIBits = 0x7e91c7b0 > > Из переданных в функцию параметров, > некоторые действительно имели нулевое > значение: > > dc->physDev = 0x0011bf00 hbitmap = 0x000001d4 startscan = 0x00000000 lines = > 0x00000064 bits = 0x00000000 info = 0x00000000 coloruse = 0x00000000 > Тогда похоже, что pSetDIBits падала из-за нулевого const BITMAPINFO *info Надеюсь я не обижу уточнением, что pSetDIBits == X11DRV_SetDIBits ? Случайно не туда нажал, извините.. Понятно, что тест нужно писать для функции SetOwnerDC, которой передаётся объект типа BITMAP. Также поскольку ошибка - read access, значит проблема не в нулевом указателе на функцию (был бы exec access), а в указателе на какие-то данные. Также при каждом падении выводится backtrace, из которого понятно, в каком месте программы (и в какой строчке) произошло падение. С ним можно было бы меньше гадать, где именно падаем. В общем я разобрался почему происходит падение wine. Все из-за вызова ф-ции CreateDIBitmap и передачи ей CBM_INIT, с одновременным BITMAPINFO *data равным NULL. Что-нибудь вроде такого вызова: hbmp = CreateDIBitmap(hdc, &bmih, CBM_INIT, &pixel, NULL, DIB_RGB_COLORS); После чего в ходе выполнения этот NULL передается ф-ции DIB_GetBitmapInfo. Она делает header->biSize, а header и есть этот параметр равный NULL. Все падает. Конечно вряд ли кто-нибудь допустит такой вызов с CBM_INIT и NULL. Но можно на всякий случай сделать патч с праверкой header на NULL? В винде, все-таки, такой вызов проходит нормально. (In reply to comment #10) > Конечно вряд ли кто-нибудь допустит такой > вызов с CBM_INIT и NULL. Но можно на всякий случай > сделать патч с праверкой header на NULL? В винде, > все-таки, такой вызов проходит нормально. > Отлично! Наверное правильным будет сделать исправление к функции и сразу тест, показывающий, что функция что-то возвращает при таком сочетании параметров и не падает. То есть даже не надо todo_wine для таких случаев ставить и сразу его убирать. Надо сделать исправление с тестом и отослать одним файлом. С тестом для BITMAP_SetOwnerDC у меня ничего не получается. Практически все вызовы сопровождаются проверкой: if (!bitmap->funcs && !BITMAP_SetOwnerDC( handle, dc )) т.е. если bitmap->funcs уже есть то ф-ция даже не вызывается. Есть еще вызов в CreateDIBitmap, но перед ним handle создается заново, т.е. bitmap->funcs тоже 0. Один вызов есть в BRUSH_SelectObject: BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc ); но заранее задать brush->logbrush.lbHatch нельзя - объект внутренний. Опять же bitmap->funcs оказывается равен 0. Проверить требуется только то, как ведёт себя функция BITMAP_SetOwnerDC Думаю можно создать bitmap, даже с пустым набором функций. А затем присвоить bitmap->funcs какое-нибудь значение. А затем проверить перезапишется ли оно после вызова BITMAP_SetOwnerDC. Даже не обязательно "правильно" создавать bitmap и DC. Можно просто посмотреть код BITMAP_SetOwnerDC и вручную заполнить те поля, которые она использует Ой! что-то я не то написал. Известно, что использует BITMAP_SetOwnerDC в wine, но не извесно как она устоена в винде. Так что вручную заполнять bitmap и DC всё же не стоит (In reply to comment #14) > Ой! что-то я не то написал. Известно, что > использует BITMAP_SetOwnerDC в wine, но не извесно как > она устоена в винде. Т.к. она не маркирована WINAPI, то с 90% вероятностью такой функции в Win API нет. > Так что вручную > заполнять bitmap и DC всё же не стоит > (In reply to comment #15) > (In reply to comment #14) > > Ой! что-то я не то написал. Известно, что > > использует BITMAP_SetOwnerDC в wine, но не извесно как > > она устоена в винде. > > Т.к. она не маркирована WINAPI, то с 90% > вероятностью такой функции в Win API нет. Ну WINAPI это макрос, определяющий соглашение о вызове (calling convention) этой функции. В основном конечно все внешние функции его используют, но прямой связи с WinAPI таки нет. Ну и конечно никой BITMAP_SetOwnerDC в Windows нет Тестировать её можно через CreateDIBitmap или SelectObject, из которых она вызывается. Но в общем оставим пока эту задачу. (In reply to comment #16) > > Т.к. она не маркирована WINAPI, то с 90% > > вероятностью такой функции в Win API нет. > Ну WINAPI это макрос, определяющий соглашение > о вызове (calling convention) этой функции. В > основном конечно все внешние функции его > используют, но прямой связи с WinAPI таки нет. :))) Конечно и ёжику понятно, что это соглашение о вызове. Я просто отметил закономерность, которую ты и указал: >В > основном конечно все внешние функции его > используют, но прямой связи с WinAPI таки нет. С таким же успехом я мог написать, что это название функции не соответствует принятому стилю именования функций Win32 API. (In reply to comment #17) > С таким же успехом я мог написать, что это > название функции не соответствует > принятому стилю именования функций Win32 API. Ну скорее даже можно однозначно утверждать что функции с подобными префиксами - внутренние для библиотек проекта Wine и не экспортируются. > Ну и конечно никой BITMAP_SetOwnerDC в Windows нет
> Тестировать её можно через CreateDIBitmap или
> SelectObject, из которых она вызывается.
>
Да, действительно! Я как-то сразу не заметил :(
Да, тут я с самого начала был неправ: Нельзя писать тест на не winapi-шную функцию |