Skip to content

Commit

Permalink
Split Java Access Bridge calls to fix NVDA crashes when selecting who…
Browse files Browse the repository at this point in the history
…le text in specific source files in Android studio (#17604)

fixes #17418

Summary of the issue:
Nvda crashes when selecting whole text in specific source files in Android Studio and IntelliJ Idea

Description of user facing changes:
NVDA should no longer crash.

Description of development approach
Java Access Bridge has a buffer limit of 10240 characters for the text. If the text is too large to fit on this buffer size, NVDA will split the calls to take the buffer size in account.

Testing strategy:
Tested with IntelliJ idea and the file provided on the issue.

Known issues with pull request:
No known issues were identified.
  • Loading branch information
thgcode authored Jan 20, 2025
1 parent 19296bf commit 0be66d5
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
34 changes: 33 additions & 1 deletion source/JABHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,13 @@ def getAccessibleTextSelectionInfo(self):
bridgeDll.getAccessibleTextSelectionInfo(self.vmID, self.accContext, byref(textSelectionInfo))
return textSelectionInfo

def getAccessibleTextRange(self, start, end):
def _javaGetAccessibleTextRange(self, start: int, end: int) -> str:
"""Helper method that performs the Java Access Bridge call to obtain the text of this object based on a (start, end) range.
:param start: The start index to get from, inclusive.
:param end: The end index to fetch to, exclusive.
:return: the text within the given indices as a string.
"""
length = (end + 1) - start
if length <= 0:
return ""
Expand All @@ -656,6 +662,32 @@ def getAccessibleTextRange(self, start, end):
bridgeDll.getAccessibleTextRange(self.vmID, self.accContext, start, end, buf, length)
return textUtils.getTextFromRawBytes(buf.raw, numChars=length, encoding=textUtils.WCHAR_ENCODING)

# Constant gotten from AccessBridgePackages.h,
# minus one to accommodate the null character
MAX_BUFFER_SIZE = 10239

def getAccessibleTextRange(self, start: int, end: int) -> str:
"""Obtains the text of this object based on a (start, end) range.
If the text is too large to fit in the buffer, this method will split the Java Access Bridge calls in chunks to get the whole text.
:param start: The start index to get from, inclusive.
:param end: The end index to fetch to, exclusive.
:return: the text within the given indices as a string.
"""
length = (end + 1) - start
if length < self.MAX_BUFFER_SIZE:
# Fast path: perform the Java Access Bridge call directly
return self._javaGetAccessibleTextRange(start, end)

text = []
while start <= end:
bufferSize = min(self.MAX_BUFFER_SIZE, length)
text.append(self._javaGetAccessibleTextRange(start, start + bufferSize - 1))
start += bufferSize
length -= bufferSize

return "".join(text)

def getAccessibleTextLineBounds(self, index):
index = max(index, 0)
log.debug("lineBounds: index %s" % index)
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Prefix matching on command line flags, e.g. using `--di` for `--disable-addons`

### Bug Fixes

* NVDA will no longer crash when selecting all text in certain source files in Android Studio or IntelliJ Idea. (#17418, @thgcode)
* Math reading has been fixed for some web elements.
Specifically, MathML inside of span and other elements that have the attribute `role="math"`. (#15058)
* Native support for the Dot Pad tactile graphics device from Dot Inc as a multiline braille display. (#17007)
Expand Down

0 comments on commit 0be66d5

Please sign in to comment.