mabe02 / lanterna

Java library for creating text-based GUIs
GNU Lesser General Public License v3.0
2.23k stars 243 forks source link

StringIndexOutOfBoundsException in CJK character handling #544

Closed schuettec closed 3 years ago

schuettec commented 3 years ago

Hi, nice library, thanks for that work! I got a StringIndexOutOfBoundsException in one of my applications. I tried to build an SSCCE but I cannot reproduce the bug in a short example. In my application I use two nested panels, basically a BorderLayout as parent and a GridLayout in a child component. When showing a message dialog using

    new MessageDialogBuilder().setTitle(title)
        .setText(errorMessage)
        .addButton(MessageDialogButton.OK)
        .build()
        .showDialog(gui);

the following exception occurs:

java.lang.StringIndexOutOfBoundsException: String index out of range: 84
    at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48)
    at java.base/java.lang.String.charAt(String.java:711)
    at com.googlecode.lanterna.TerminalTextUtils.getStringCharacterIndex(TerminalTextUtils.java:230)
    at com.googlecode.lanterna.TerminalTextUtils.getWordWrappedText(TerminalTextUtils.java:323)
    at com.googlecode.lanterna.gui2.Label$1.drawComponent(Label.java:259)
    at com.googlecode.lanterna.gui2.Label$1.drawComponent(Label.java:234)
    at com.googlecode.lanterna.gui2.AbstractComponent.draw(AbstractComponent.java:239)
    at com.googlecode.lanterna.gui2.Panel$DefaultPanelRenderer.drawComponent(Panel.java:273)
    at com.googlecode.lanterna.gui2.Panel$DefaultPanelRenderer.drawComponent(Panel.java:229)
    at com.googlecode.lanterna.gui2.AbstractComponent.draw(AbstractComponent.java:239)
    at com.googlecode.lanterna.gui2.AbstractBasePane$ContentHolder$1.drawComponent(AbstractBasePane.java:474)
    at com.googlecode.lanterna.gui2.AbstractBasePane$ContentHolder$1.drawComponent(AbstractBasePane.java:451)
    at com.googlecode.lanterna.gui2.AbstractComponent.draw(AbstractComponent.java:239)
    at com.googlecode.lanterna.gui2.AbstractBasePane.draw(AbstractBasePane.java:85)
    at com.googlecode.lanterna.gui2.AbstractWindow.draw(AbstractWindow.java:130)
    at com.googlecode.lanterna.gui2.MultiWindowTextGUI.drawGUI(MultiWindowTextGUI.java:275)
    at com.googlecode.lanterna.gui2.AbstractTextGUI.updateScreen(AbstractTextGUI.java:120)
    at com.googlecode.lanterna.gui2.MultiWindowTextGUI.updateScreen(MultiWindowTextGUI.java:236)
    at com.googlecode.lanterna.gui2.AbstractTextGUIThread.processEventsAndUpdate(AbstractTextGUIThread.java:85)
    at com.googlecode.lanterna.gui2.MultiWindowTextGUI.waitForWindowToClose(MultiWindowTextGUI.java:508)
    at com.googlecode.lanterna.gui2.AbstractWindow.waitUntilClosed(AbstractWindow.java:322)
    at com.googlecode.lanterna.gui2.dialogs.DialogWindow.showDialog(DialogWindow.java:54)
    at com.googlecode.lanterna.gui2.dialogs.MessageDialog.showDialog(MessageDialog.java:78)
    at com.schuettec.morpheus.standalone.client.plugin.MorpheusTerminalClient.showError(MorpheusTerminalClient.java:277)
    at com.schuettec.morpheus.standalone.client.plugin.MorpheusTerminalClient.showError(MorpheusTerminalClient.java:266)
    at com.schuettec.morpheus.standalone.client.plugin.MorpheusTerminalClient.showError(MorpheusTerminalClient.java:262)
    at com.schuettec.morpheus.standalone.client.plugin.MorpheusTerminalClient.showError(MorpheusTerminalClient.java:271)
    at com.schuettec.morpheus.standalone.client.plugin.MorpheusTerminalClient.showErrorAndReturnToLogin(MorpheusTerminalClient.java:246)
    at com.schuettec.morpheus.standalone.client.plugin.MorpheusTerminalClient$1.run(MorpheusTerminalClient.java:138)
    at com.googlecode.lanterna.gui2.Button.lambda$new$0(Button.java:71)
    at com.googlecode.lanterna.gui2.Button.triggerActions(Button.java:95)
    at com.googlecode.lanterna.gui2.Button.handleKeyStroke(Button.java:87)
    at com.googlecode.lanterna.gui2.AbstractInteractableComponent.handleInput(AbstractInteractableComponent.java:145)
    at com.googlecode.lanterna.gui2.AbstractBasePane.doHandleInput(AbstractBasePane.java:167)
    at com.googlecode.lanterna.gui2.AbstractBasePane.handleInput(AbstractBasePane.java:103)
    at com.googlecode.lanterna.gui2.AbstractWindow.handleInput(AbstractWindow.java:135)
    at com.googlecode.lanterna.gui2.MultiWindowTextGUI.handleInput(MultiWindowTextGUI.java:365)
    at com.googlecode.lanterna.gui2.AbstractTextGUI.processInput(AbstractTextGUI.java:94)
    at com.googlecode.lanterna.gui2.AbstractTextGUIThread.processEventsAndUpdate(AbstractTextGUIThread.java:77)
    at com.googlecode.lanterna.gui2.MultiWindowTextGUI.waitForWindowToClose(MultiWindowTextGUI.java:508)
    at com.googlecode.lanterna.gui2.AbstractWindow.waitUntilClosed(AbstractWindow.java:322)
    at com.googlecode.lanterna.gui2.MultiWindowTextGUI.addWindowAndWait(MultiWindowTextGUI.java:484)
    at com.schuettec.morpheus.standalone.client.plugin.MorpheusTerminalClient.run(MorpheusTerminalClient.java:103)
    at java.base/java.lang.Thread.run(Thread.java:832)

I tried to analyse the problem: The string that is processed in method TerminalTextUtils.getStringCharacterIndex(TerminalTextUtils.java:230) has a length of 83. The method TerminalTextUtils.getWordWrappedText(TerminalTextUtils.java:323) in the parent stack frame uses some width of a component, so maxWidth is 86. The loop in TerminalTextUtils.getStringCharacterIndex(TerminalTextUtils.java:230) overruns the string length.

This might be a simple bug I think.

schuettec commented 3 years ago

After fiddling around I found out that the error occurs if the terminal window is not big enough to display the message dialog box. I put a stacktrace in the message dialog and it exceeds the window width.

What can I do?

avl42 commented 3 years ago

Best thing to do would be creating a pull request with a fix for it ;-)

Otherwise, someone else might look into it and - unless the other one is mabe02 himself - create a PR as well...

I likely won't get into it in the next few days, but maybe more likely towards the weekend.

On Sat, May 1, 2021 at 10:16 AM Christopher Schütte < @.***> wrote:

After fiddling around I found out that the error occurs if the terminal window is not big enough to display the message dialog box. I put a stacktrace in the message dialog and it exceeds the window width.

What can I do?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mabe02/lanterna/issues/544#issuecomment-830578190, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABIDBMSGWBZQJGCU5P7XT5LTLO2FLANCNFSM436CTQMQ .

schuettec commented 3 years ago

Hi, I figured out that the error came from an invalid layout data: BorderLayout settings were passed into a GridLayout. I think the API should prevent such errors with an exception but this seems only to happen if the actual layout becomes visible.

The above exception is a consequence of this. I will close this one.