Skip to content

Commit

Permalink
Gecko vbuf backend: Gecko <= 1.9.2.9 (Firefox <= 3.6.9) crashes when …
Browse files Browse the repository at this point in the history
…we attempt to retrieve table headers on certain table cells. We have no way of detecting when this is going to happen, so disable table headers completely for Gecko <= 1.9.2.9.

This is fixed in Gecko 1.9.2.10 (Firefox 3.6.10), which will be released soon.
Note that this crash also occurs in earlier Firefox 4 betas and nightlies. We don't protect against this for Firefox 4. Firefox 4 testers should use a recent nightly.
This required moving fillVBuf and fillTableCellInfo_IATable2 into the GeckoVBufBackend_t class. There is also a new method called versionSpecificInit which retrieves the version information and sets the flag to disable table headers.

Fixes #807.
  • Loading branch information
jcsteh committed Sep 14, 2010
1 parent 96615ff commit e6ccf99
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 6 deletions.
59 changes: 53 additions & 6 deletions source/NVDAHelper/vbufBackends/gecko_ia2/gecko_ia2.cpp
Expand Up @@ -141,7 +141,7 @@ inline void fillTableCellInfo_IATable(VBufStorage_controlFieldNode_t* node, IAcc
DEBUG_MSG(L"IAccessibleTable::get_rowColumnExtentsAtIndex failed, result " << res);
}

inline void fillTableCellInfo_IATable2(VBufStorage_controlFieldNode_t* node, IAccessibleTableCell* paccTableCell) {
inline void GeckoVBufBackend_t::fillTableCellInfo_IATable2(VBufStorage_controlFieldNode_t* node, IAccessibleTableCell* paccTableCell) {
int res;
wostringstream s;

Expand All @@ -166,6 +166,9 @@ inline void fillTableCellInfo_IATable2(VBufStorage_controlFieldNode_t* node, IAc
}
}

if (this->shouldDisableTableHeaders)
return;

IUnknown** headerCells;
long nHeaderCells;
IAccessible2* headerCellPacc = NULL;
Expand Down Expand Up @@ -228,7 +231,47 @@ inline void fillTableCellInfo_IATable2(VBufStorage_controlFieldNode_t* node, IAc
}
}

VBufStorage_fieldNode_t* fillVBuf(IAccessible2* pacc, VBufStorage_buffer_t* buffer, VBufStorage_controlFieldNode_t* parentNode, VBufStorage_fieldNode_t* previousNode, IAccessibleTable* paccTable=NULL, IAccessibleTable2* paccTable2=NULL, long tableID=0) {
void GeckoVBufBackend_t::versionSpecificInit(IAccessible2* pacc) {
IServiceProvider* serv = NULL;
if (pacc->QueryInterface(IID_IServiceProvider, (void**)&serv) != S_OK)
return;
IAccessibleApplication* iaApp = NULL;
if (serv->QueryService(IID_IAccessibleApplication, IID_IAccessibleApplication, (void**)&iaApp) != S_OK) {
serv->Release();
return;
}
serv->Release();
serv = NULL;

BSTR toolkitName = NULL;
if (iaApp->get_toolkitName(&toolkitName) != S_OK) {
iaApp->Release();
return;
}
BSTR toolkitVersion = NULL;
if (iaApp->get_toolkitVersion(&toolkitVersion) != S_OK) {
iaApp->Release();
SysFreeString(toolkitName);
return;
}
iaApp->Release();
iaApp = NULL;

if (wcscmp(toolkitName, L"Gecko") == 0) {
// Gecko <= 1.9.2.9 will crash if we try to retrieve headers on some table cells, so disable them.
UINT toolkitVersionLen = SysStringLen(toolkitVersion);
this->shouldDisableTableHeaders = (toolkitVersionLen >= 7 &&
wcsncmp(toolkitVersion, L"1.9.2.", 6) == 0 &&
// If there is another digit after 1.9.2.n, this is >= 1.9.2.10.
(toolkitVersionLen <= 7 || !iswdigit(toolkitVersion[7]))
);
}

SysFreeString(toolkitName);
SysFreeString(toolkitVersion);
}

VBufStorage_fieldNode_t* GeckoVBufBackend_t::fillVBuf(IAccessible2* pacc, VBufStorage_buffer_t* buffer, VBufStorage_controlFieldNode_t* parentNode, VBufStorage_fieldNode_t* previousNode, IAccessibleTable* paccTable, IAccessibleTable2* paccTable2, long tableID) {
int res;
DEBUG_MSG(L"Entered fillVBuf, with pacc at "<<pacc<<L", parentNode at "<<parentNode<<L", previousNode "<<previousNode);
assert(buffer); //buffer can't be NULL
Expand Down Expand Up @@ -453,7 +496,7 @@ VBufStorage_fieldNode_t* fillVBuf(IAccessible2* pacc, VBufStorage_buffer_t* buff
parentNode->addAttribute(L"table-id", s.str());
if (res == S_OK) {
// IAccessibleTable2
fillTableCellInfo_IATable2(parentNode, paccTableCell);
this->fillTableCellInfo_IATable2(parentNode, paccTableCell);
paccTableCell->Release();
paccTableCell = NULL;
} else // IAccessibleTable
Expand Down Expand Up @@ -652,7 +695,7 @@ VBufStorage_fieldNode_t* fillVBuf(IAccessible2* pacc, VBufStorage_buffer_t* buff
if(childDefaction) SysFreeString(childDefaction);
#endif
DEBUG_MSG(L"calling fillVBuf with childPacc ");
if((tempNode=fillVBuf(childPacc,buffer,parentNode,previousNode,paccTable,paccTable2,tableID))!=NULL) {
if((tempNode=this->fillVBuf(childPacc,buffer,parentNode,previousNode,paccTable,paccTable2,tableID))!=NULL) {
previousNode=tempNode;
} else {
DEBUG_MSG(L"Error in fillVBuf");
Expand Down Expand Up @@ -706,7 +749,7 @@ VBufStorage_fieldNode_t* fillVBuf(IAccessible2* pacc, VBufStorage_buffer_t* buff
}
if(childPacc) {
DEBUG_MSG(L"calling _filVBufHelper with child object ");
if((tempNode=fillVBuf(childPacc,buffer,parentNode,previousNode,paccTable,paccTable2,tableID))!=NULL) {
if((tempNode=this->fillVBuf(childPacc,buffer,parentNode,previousNode,paccTable,paccTable2,tableID))!=NULL) {
previousNode=tempNode;
} else {
DEBUG_MSG(L"Error in calling fillVBuf");
Expand Down Expand Up @@ -958,8 +1001,12 @@ void GeckoVBufBackend_t::render(VBufStorage_buffer_t* buffer, int docHandle, int
DEBUG_MSG(L"Could not get IAccessible2, returning");
return;
}
if (!oldNode) {
// This is the root node.
this->versionSpecificInit(pacc);
}
DEBUG_MSG(L"Calling fillVBuf");
fillVBuf(pacc, buffer, NULL, NULL);
this->fillVBuf(pacc, buffer, NULL, NULL);
pacc->Release();
DEBUG_MSG(L"Rendering done");
}
Expand Down
10 changes: 10 additions & 0 deletions source/NVDAHelper/vbufBackends/gecko_ia2/gecko_ia2.h
Expand Up @@ -18,6 +18,16 @@ This license can be found at:
#include <vbufBase/backend.h>

class GeckoVBufBackend_t: public VBufBackend_t {
private:

VBufStorage_fieldNode_t* fillVBuf(IAccessible2* pacc, VBufStorage_buffer_t* buffer, VBufStorage_controlFieldNode_t* parentNode, VBufStorage_fieldNode_t* previousNode, IAccessibleTable* paccTable=NULL, IAccessibleTable2* paccTable2=NULL, long tableID=0);

void versionSpecificInit(IAccessible2* pacc);

void fillTableCellInfo_IATable2(VBufStorage_controlFieldNode_t* node, IAccessibleTableCell* paccTableCell);

bool shouldDisableTableHeaders;

protected:

static void CALLBACK renderThread_winEventProcHook(HWINEVENTHOOK hookID, DWORD eventID, HWND hwnd, long objectID, long childID, DWORD threadID, DWORD time);
Expand Down

0 comments on commit e6ccf99

Please sign in to comment.