app_server & Application Kit: Fix bitmap cursor handling.
Using a memcpy here is supremely dangerous, because we are writing to an app_server buffer that we chose the length for, but using a size that came from the client. And, indeed, because the buffer can contain padding if the BBitmap was allocated with a non-standard BytesPerRow, we will overflow the buffer and corrupt memory, causing app_server to crash. So, instead, reorganize parameters a bit, and pass BytesPerRow along with the other data needed to instantiate the bitmap, and then use ImportBits. Fixes an app_server crash I triggered with the experimental libX11 compatibility layer.
This commit is contained in:
@@ -96,20 +96,21 @@ BCursor::BCursor(const BBitmap* bitmap, const BPoint& hotspot)
|
|||||||
if (bitmap == NULL)
|
if (bitmap == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int32 size = bitmap->BitsLength();
|
|
||||||
BRect bounds = bitmap->Bounds();
|
BRect bounds = bitmap->Bounds();
|
||||||
color_space colorspace = bitmap->ColorSpace();
|
color_space colorspace = bitmap->ColorSpace();
|
||||||
void* bits = bitmap->Bits();
|
void* bits = bitmap->Bits();
|
||||||
|
int32 size = bitmap->BitsLength();
|
||||||
if (bits == NULL || size <= 0)
|
if (bits == NULL || size <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Send data directly to server
|
// Send data directly to server
|
||||||
BPrivate::AppServerLink link;
|
BPrivate::AppServerLink link;
|
||||||
link.StartMessage(AS_CREATE_CURSOR_BITMAP);
|
link.StartMessage(AS_CREATE_CURSOR_BITMAP);
|
||||||
link.Attach<int32>(size);
|
|
||||||
link.Attach<BRect>(bounds);
|
link.Attach<BRect>(bounds);
|
||||||
link.Attach<color_space>(colorspace);
|
|
||||||
link.Attach<BPoint>(hotspot);
|
link.Attach<BPoint>(hotspot);
|
||||||
|
link.Attach<color_space>(colorspace);
|
||||||
|
link.Attach<int32>(bitmap->BytesPerRow());
|
||||||
|
link.Attach<int32>(size);
|
||||||
link.Attach(bits, size);
|
link.Attach(bits, size);
|
||||||
|
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|||||||
@@ -1204,16 +1204,17 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
|||||||
|
|
||||||
status_t status = B_ERROR;
|
status_t status = B_ERROR;
|
||||||
|
|
||||||
int32 size = 0;
|
int32 size = 0, bytesPerRow = 0;
|
||||||
BRect cursorRect;
|
BRect cursorRect;
|
||||||
color_space colorspace = B_RGBA32;
|
color_space colorspace = B_RGBA32;
|
||||||
BPoint hotspot;
|
BPoint hotspot;
|
||||||
ServerCursor* cursor = NULL;
|
ServerCursor* cursor = NULL;
|
||||||
|
|
||||||
if (link.Read<int32>(&size) == B_OK
|
if (link.Read<BRect>(&cursorRect) == B_OK
|
||||||
&& link.Read<BRect>(&cursorRect) == B_OK
|
|
||||||
&& link.Read<color_space>(&colorspace) == B_OK
|
|
||||||
&& link.Read<BPoint>(&hotspot) == B_OK
|
&& link.Read<BPoint>(&hotspot) == B_OK
|
||||||
|
&& link.Read<color_space>(&colorspace) == B_OK
|
||||||
|
&& link.Read<int32>(&bytesPerRow) == B_OK
|
||||||
|
&& link.Read<int32>(&size) == B_OK
|
||||||
&& size > 0) {
|
&& size > 0) {
|
||||||
|
|
||||||
BStackOrHeapArray<uint8, 256> byteArray(size);
|
BStackOrHeapArray<uint8, 256> byteArray(size);
|
||||||
@@ -1225,7 +1226,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
|
|||||||
if (cursor == NULL)
|
if (cursor == NULL)
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
else
|
else
|
||||||
memcpy(cursor->Bits(), byteArray, size);
|
cursor->ImportBits(byteArray, size, bytesPerRow, colorspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user