* Do not trust the client! ServerFont::GetEscapements() now takes a

parameter for the length of the arrays, so that even if the char/byte
  counts do not match, no memory is overwritten anymore.
  This fixes bug #1862; .canna obviously contains invalid UTF-8 
  characters, or there is a bug in StyledEdit (or deeper) and it doesn't 
  call BFont::GetEscapements() correctly.
* Fixed some cases of unchecked allocations in the font handling methods
  of ServerApp, added TODOs to all other ones.
* Improved error code when creating a window fails.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24160 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-02-28 00:22:48 +00:00
parent e705558bb9
commit a4de7fa0fa
3 changed files with 88 additions and 41 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2007, Haiku.
* Copyright 2001-2008, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -62,15 +62,14 @@
//#define DEBUG_SERVERAPP
#ifdef DEBUG_SERVERAPP
# define STRACE(x) printf x
# define STRACE(x) debug_printf x
#else
# define STRACE(x) ;
#endif
//#define DEBUG_SERVERAPP_FONT
#ifdef DEBUG_SERVERAPP_FONT
# define FTRACE(x) printf x
# define FTRACE(x) debug_printf x
#else
# define FTRACE(x) ;
#endif
@ -1414,6 +1413,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
size = 0.0f;
}
// TODO: don't use the stack for this - numStrings could be large
float widthArray[numStrings];
int32 lengthArray[numStrings];
char *stringArray[numStrings];
@ -1599,6 +1599,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
link.Read<int32>(&numChars);
link.Read<int32>(&numBytes);
// TODO: proper error checking
char* charArray = new (nothrow) char[numBytes];
link.Read(charArray, numBytes);
@ -1611,6 +1612,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
font.SetFalseBoldWidth(falseBoldWidth);
font.SetFlags(flags);
// TODO: proper error checking
BShape** shapes = new (nothrow) BShape*[numChars];
status = font.GetGlyphShapes(charArray, numChars, shapes);
if (status == B_OK) {
@ -1647,6 +1649,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
int32 numChars, numBytes;
link.Read<int32>(&numChars);
link.Read<int32>(&numBytes);
// TODO: proper error checking
char* charArray = new (nothrow) char[numBytes];
link.Read(charArray, numBytes);
@ -1686,6 +1689,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
uint32 numBytes;
link.Read<uint32>(&numBytes);
// TODO: proper error checking
char* charArray = new (nothrow) char[numBytes];
link.Read(charArray, numBytes);
@ -1748,7 +1752,24 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
uint32 numBytes;
link.Read<uint32>(&numBytes);
char *charArray = new (nothrow) char[numBytes];
BPoint *escapements = new (nothrow) BPoint[numChars];
BPoint *offsets = NULL;
if (wantsOffsets)
offsets = new (nothrow) BPoint[numChars];
if (charArray == NULL || escapements == NULL
|| (offsets == NULL && wantsOffsets)) {
delete[] charArray;
delete[] escapements;
delete[] offsets;
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
ServerFont font;
@ -1759,20 +1780,15 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
font.SetRotation(rotation);
font.SetFlags(flags);
BPoint *escapements = new (nothrow) BPoint[numChars];
BPoint *offsets = NULL;
if (wantsOffsets)
offsets = new (nothrow) BPoint[numChars];
status = font.GetEscapements(charArray, numBytes, delta,
escapements, offsets);
status = font.GetEscapements(charArray, numBytes, numChars,
delta, escapements, offsets);
if (status == B_OK) {
fLink.StartMessage(B_OK);
for (int32 i = 0; i < numChars; i++)
fLink.Attach<BPoint>(escapements[i]);
if (wantsOffsets) {
if (offsets) {
for (int32 i = 0; i < numChars; i++)
fLink.Attach<BPoint>(offsets[i]);
}
@ -1781,7 +1797,6 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
delete[] escapements;
delete[] offsets;
} else
fLink.StartMessage(status);
@ -1831,10 +1846,18 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
uint32 numBytes;
link.Read<uint32>(&numBytes);
char* charArray = new (nothrow) char[numBytes];
link.Read(charArray, numBytes);
char* charArray = new (nothrow) char[numBytes];
float* escapements = new (nothrow) float[numChars];
if (charArray == NULL || escapements == NULL) {
delete[] charArray;
delete[] escapements;
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
// figure out escapements
@ -1846,8 +1869,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
font.SetRotation(rotation);
font.SetFlags(flags);
status = font.GetEscapements(charArray, numBytes, delta,
escapements);
status = font.GetEscapements(charArray, numBytes, numChars,
delta, escapements);
if (status == B_OK) {
fLink.StartMessage(B_OK);
@ -1917,6 +1940,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
uint32 numBytes;
link.Read<uint32>(&numBytes);
// TODO: proper error checking
char *charArray = new (nothrow) char[numBytes];
link.Read(charArray, numBytes);
@ -2574,7 +2598,7 @@ ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link,
frame.bottom = frame.top + 1;
}
status_t status = B_ERROR;
status_t status = B_NO_MEMORY;
ServerWindow *window = NULL;
if (code == AS_CREATE_OFFSCREEN_WINDOW) {
@ -2583,7 +2607,8 @@ ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link,
if (bitmap != NULL) {
window = new (nothrow) OffscreenServerWindow(title, this, clientReplyPort,
looperPort, token, bitmap);
}
} else
status = B_ERROR;
} else {
window = new (nothrow) ServerWindow(title, this, clientReplyPort, looperPort, token);
STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n",

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2007, Haiku.
* Copyright 2001-2008, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -496,28 +496,36 @@ ServerFont::GetEdges(const char* string, int32 numBytes,
class BPointEscapementConsumer {
public:
BPointEscapementConsumer(BPoint* escapements, BPoint* offsets, float size)
: fEscapements(escapements)
, fOffsets(offsets)
, fSize(size)
public:
BPointEscapementConsumer(BPoint* escapements, BPoint* offsets,
int32 numChars, float size)
:
fEscapements(escapements),
fOffsets(offsets),
fNumChars(numChars),
fSize(size)
{
}
void Start() {}
void Finish(double x, double y) {}
void ConsumeEmptyGlyph(int32 index, uint32 charCode, double x, double y)
{
_Set(index, 0, 0);
}
bool ConsumeGlyph(int32 index, uint32 charCode, const GlyphCache* glyph,
FontCacheEntry* entry, double x, double y)
{
_Set(index, glyph->advance_x, glyph->advance_y);
return true;
return _Set(index, glyph->advance_x, glyph->advance_y);
}
private:
inline void _Set(int32 index, double x, double y)
private:
inline bool _Set(int32 index, double x, double y)
{
if (index >= fNumChars)
return false;
fEscapements[index].x = x / fSize;
fEscapements[index].y = y / fSize;
if (fOffsets) {
@ -529,16 +537,18 @@ class BPointEscapementConsumer {
fOffsets[index].x = 0;
fOffsets[index].y = 0;
}
return true;
}
BPoint* fEscapements;
BPoint* fOffsets;
int32 fNumChars;
float fSize;
};
status_t
ServerFont::GetEscapements(const char* string, int32 numBytes,
ServerFont::GetEscapements(const char* string, int32 numBytes, int32 numChars,
escapement_delta delta, BPoint escapementArray[],
BPoint offsetArray[]) const
{
@ -547,7 +557,8 @@ ServerFont::GetEscapements(const char* string, int32 numBytes,
bool kerning = true; // TODO make this a property?
BPointEscapementConsumer consumer(escapementArray, offsetArray, fSize);
BPointEscapementConsumer consumer(escapementArray, offsetArray, numChars,
fSize);
if (GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
&delta, kerning, fSpacing))
return B_OK;
@ -557,34 +568,42 @@ ServerFont::GetEscapements(const char* string, int32 numBytes,
class WidthEscapementConsumer {
public:
WidthEscapementConsumer(float* widths, float size)
: fWidths(widths)
, fSize(size)
public:
WidthEscapementConsumer(float* widths, int32 numChars, float size)
:
fWidths(widths),
fNumChars(numChars),
fSize(size)
{
}
void Start() {}
void Finish(double x, double y) {}
void ConsumeEmptyGlyph(int32 index, uint32 charCode, double x, double y)
{
fWidths[index] = 0.0;
}
bool ConsumeGlyph(int32 index, uint32 charCode, const GlyphCache* glyph,
FontCacheEntry* entry, double x, double y)
{
if (index >= fNumChars)
return false;
fWidths[index] = glyph->advance_x / fSize;
return true;
}
private:
float* fWidths;
int32 fNumChars;
float fSize;
};
status_t
ServerFont::GetEscapements(const char* string, int32 numBytes,
ServerFont::GetEscapements(const char* string, int32 numBytes, int32 numChars,
escapement_delta delta, float widthArray[]) const
{
if (!string || numBytes <= 0 || !widthArray)
@ -592,7 +611,7 @@ ServerFont::GetEscapements(const char* string, int32 numBytes,
bool kerning = true; // TODO make this a property?
WidthEscapementConsumer consumer(widthArray, fSize);
WidthEscapementConsumer consumer(widthArray, numChars, fSize);
if (GlyphLayoutEngine::LayoutGlyphs(consumer, *this, string, numBytes,
&delta, kerning, fSpacing))
return B_OK;
@ -813,7 +832,8 @@ ServerFont::TruncateString(BString* inOut, uint32 mode, float width) const
// get the escapement of each glyph in font units
float *escapementArray = new float[numChars];
static escapement_delta delta = (escapement_delta){ 0.0, 0.0 };
if (GetEscapements(string, length, delta, escapementArray) == B_OK) {
if (GetEscapements(string, length, numChars, delta, escapementArray)
== B_OK) {
truncate_string(string, mode, width, result, escapementArray, fSize,
ellipsisWidth, length, numChars);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2007, Haiku.
* Copyright 2001-2008, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -125,12 +125,14 @@ class ServerFont {
edge_info edgeArray[]) const;
status_t GetEscapements(const char charArray[],
int32 numBytes, escapement_delta delta,
int32 numBytes, int32 numChars,
escapement_delta delta,
BPoint escapementArray[],
BPoint offsetArray[]) const;
status_t GetEscapements(const char charArray[],
int32 numBytes, escapement_delta delta,
int32 numBytes, int32 numChars,
escapement_delta delta,
float widthArray[]) const;
status_t GetBoundingBoxes(const char charArray[],