Skip to content

Commit

Permalink
Invalid regex expressions in dictionaries no longer causes crash. (#6136
Browse files Browse the repository at this point in the history
)

Fixes #4834
PR: #6136 

This change introduces a safety check when loading speech dictionaries, to ensure that nvda does not crash if the dictionaries contain invalid regex. This change also catches the same situation in the UI and informs the user that the regex is invalid.

- When adding a dictionary entry with invalid regex, the error message now states that this is a regex error and qoutes the error. It is unfortunate, but the regex error is difficult to translate.
- If a user does manage to introduce an error into a dictionary file, then the nvda will import all valid lines in the file, reporting warnings to the log for lines in the dictionary that are invalid.
  • Loading branch information
feerrenrut committed Jul 20, 2016
1 parent 8f4b4f0 commit 13e7232
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
15 changes: 13 additions & 2 deletions source/gui/settingsDialogs.py
Expand Up @@ -1252,13 +1252,24 @@ def __init__(self, parent, title=_("Edit Dictionary Entry")):
self.SetSizer(mainSizer)
self.setType(speechDictHandler.ENTRY_TYPE_ANYWHERE)
self.patternTextCtrl.SetFocus()
self.Bind(wx.EVT_BUTTON,self.onOk,id=wx.ID_OK)

def getType(self):
typeRadioValue = self.typeRadioBox.GetSelection()
if typeRadioValue == wx.NOT_FOUND:
return speechDictHandler.ENTRY_TYPE_ANYWHERE
return DictionaryEntryDialog.TYPE_LABELS_ORDERING[typeRadioValue]

def onOk(self,evt):
try:
self.dictEntry=speechDictHandler.SpeechDictEntry(self.patternTextCtrl.GetValue(),self.replacementTextCtrl.GetValue(),self.commentTextCtrl.GetValue(),bool(self.caseSensitiveCheckBox.GetValue()),self.getType())
except Exception as e:
log.debugWarning("Could not add dictionary entry due to (regex error) : %s" % e)
# Translators: This is an error message to let the user know that the dictionary entry is not valid.
gui.messageBox(_("Regular Expression error: \"%s\".")%e, _("Dictionary Entry Error"), wx.OK|wx.ICON_WARNING, self)
return
evt.Skip()

def setType(self, type):
self.typeRadioBox.SetSelection(DictionaryEntryDialog.TYPE_LABELS_ORDERING.index(type))

Expand Down Expand Up @@ -1332,7 +1343,7 @@ def OnAddClick(self,evt):
# Translators: This is the label for the add dictionary entry dialog.
entryDialog=DictionaryEntryDialog(self,title=_("Add Dictionary Entry"))
if entryDialog.ShowModal()==wx.ID_OK:
self.tempSpeechDict.append(speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),entryDialog.getType()))
self.tempSpeechDict.append(entryDialog.dictEntry)
self.dictList.Append((entryDialog.commentTextCtrl.GetValue(),entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),self.offOn[int(entryDialog.caseSensitiveCheckBox.GetValue())],DictionaryDialog.TYPE_LABELS[entryDialog.getType()]))
index=self.dictList.GetFirstSelected()
while index>=0:
Expand All @@ -1357,7 +1368,7 @@ def OnEditClick(self,evt):
entryDialog.caseSensitiveCheckBox.SetValue(self.tempSpeechDict[editIndex].caseSensitive)
entryDialog.setType(self.tempSpeechDict[editIndex].type)
if entryDialog.ShowModal()==wx.ID_OK:
self.tempSpeechDict[editIndex]=speechDictHandler.SpeechDictEntry(entryDialog.patternTextCtrl.GetValue(),entryDialog.replacementTextCtrl.GetValue(),entryDialog.commentTextCtrl.GetValue(),bool(entryDialog.caseSensitiveCheckBox.GetValue()),entryDialog.getType())
self.tempSpeechDict[editIndex]=entryDialog.dictEntry
self.dictList.SetStringItem(editIndex,0,entryDialog.commentTextCtrl.GetValue())
self.dictList.SetStringItem(editIndex,1,entryDialog.patternTextCtrl.GetValue())
self.dictList.SetStringItem(editIndex,2,entryDialog.replacementTextCtrl.GetValue())
Expand Down
8 changes: 7 additions & 1 deletion source/speechDictHandler.py
Expand Up @@ -67,7 +67,13 @@ def load(self, fileName):
else:
temp=line.split("\t")
if len(temp) ==4:
self.append(SpeechDictEntry(temp[0].replace(r'\#','#'),temp[1].replace(r'\#','#'),comment,bool(int(temp[2])),int(temp[3])))
pattern = temp[0].replace(r'\#','#')
replace = temp[1].replace(r'\#','#')
try:
dictionaryEntry=SpeechDictEntry(pattern, replace, comment, caseSensitive=bool(int(temp[2])), type=int(temp[3]))
self.append(dictionaryEntry)
except Exception as e:
log.exception("Dictionary (\"%s\") entry invalid for \"%s\" error raised: \"%s\"" % (fileName, line, e))
comment=""
else:
log.warning("can't parse line '%s'" % line)
Expand Down

0 comments on commit 13e7232

Please sign in to comment.