Reading `ReportInfo` with `Bundle.getSerializable()` by `ReportActivity` is triggering exception when default algorithm is used for `serialVersionUID` in Termux:API plugin app when error notification created in `ResultReturner.returnData()` by `TermuxPluginUtils.sendPluginCommandErrorNotification()` is clicked.
```
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.termux/com.termux.shared.activities.ReportActivity}: android.os.BadParcelableException: Parcelable encountered IOException reading a Serializable object (name = com.termux.shared.models.ReportInfo)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4280)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4467)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:222)
at android.app.servertransaction.TransactionExecutor.executeNonLifecycleItem(TransactionExecutor.java:133)
at android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:103)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:80)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2823)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loopOnce(Looper.java:248)
at android.os.Looper.loop(Looper.java:338)
at android.app.ActivityThread.main(ActivityThread.java:9067)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)
Caused by: android.os.BadParcelableException: Parcelable encountered IOException reading a Serializable object (name = com.termux.shared.models.ReportInfo)
at android.os.Parcel.readSerializableInternal(Parcel.java:5520)
at android.os.Parcel.readValue(Parcel.java:5038)
at android.os.Parcel.readValue(Parcel.java:4702)
at android.os.Parcel.-$$Nest$mreadValue(Unknown Source:0)
at android.os.Parcel$LazyValue.apply(Parcel.java:4811)
at android.os.Parcel$LazyValue.apply(Parcel.java:4764)
at android.os.BaseBundle.unwrapLazyValueFromMapLocked(BaseBundle.java:446)
at android.os.BaseBundle.getValueAt(BaseBundle.java:426)
at android.os.BaseBundle.getValue(BaseBundle.java:397)
at android.os.BaseBundle.getValue(BaseBundle.java:380)
at android.os.BaseBundle.getValue(BaseBundle.java:373)
at android.os.BaseBundle.getSerializable(BaseBundle.java:1522)
at android.os.Bundle.getSerializable(Bundle.java:1339)
at com.termux.shared.activities.ReportActivity.updateUI(ReportActivity.java:140)
at com.termux.shared.activities.ReportActivity.onCreate(ReportActivity.java:93)
at android.app.Activity.performCreate(Activity.java:9155)
at android.app.Activity.performCreate(Activity.java:9133)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1521)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4262)
... 13 more
Caused by: java.io.InvalidClassException: com.termux.shared.models.ReportInfo; local class incompatible: stream classdesc serialVersionUID = -5165426368218339031, local class serialVersionUID = 1
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:652)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1743)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1624)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1902)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1442)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:430)
at android.os.Parcel.readSerializableInternal(Parcel.java:5507)
... 31 more
```
If using release APK with obfuscation enabled, then following exception will be triggered.
```
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.termux/com.termux.shared.activities.ReportActivity}: android.os.BadParcelableException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = I0.a)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3864)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4006)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:111)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2462)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:240)
at android.os.Looper.loop(Looper.java:351)
at android.app.ActivityThread.main(ActivityThread.java:8377)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013)
Caused by: android.os.BadParcelableException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = I0.a)
at android.os.Parcel.readSerializableInternal(Parcel.java:5113)
at android.os.Parcel.readValue(Parcel.java:4655)
at android.os.Parcel.readValue(Parcel.java:4363)
at android.os.Parcel.-$$Nest$mreadValue(Unknown Source:0)
at android.os.Parcel$LazyValue.apply(Parcel.java:4461)
at android.os.Parcel$LazyValue.apply(Parcel.java:4420)
at android.os.BaseBundle.getValueAt(BaseBundle.java:394)
at android.os.BaseBundle.getValue(BaseBundle.java:374)
at android.os.BaseBundle.getValue(BaseBundle.java:357)
at android.os.BaseBundle.getValue(BaseBundle.java:350)
at android.os.BaseBundle.getSerializable(BaseBundle.java:1451)
at android.os.Bundle.getSerializable(Bundle.java:1144)
at com.termux.shared.activities.ReportActivity.updateUI(ReportActivity.java:136)
at com.termux.shared.activities.ReportActivity.onCreate(ReportActivity.java:89)
at android.app.Activity.performCreate(Activity.java:8397)
at android.app.Activity.performCreate(Activity.java:8370)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1403)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3837)
... 12 more
Caused by: java.lang.ClassNotFoundException: I0.a
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:536)
at android.os.Parcel$2.resolveClass(Parcel.java:5090)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1733)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1624)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1902)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1442)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:430)
at android.os.Parcel.readSerializableInternal(Parcel.java:5096)
... 29 more
Caused by: java.lang.ClassNotFoundException: I0.a
... 38 more
```
Related issue https://github.com/termux/termux-api/issues/762
SD sequence (`${CSI}${N}T`) was scrolling the whole width
of the terminal instead of just between the margins.
RI sequence (`${ESC}M`, move cursor up 1 line) was doing the same.
Fixed that.
Fixes#2576 where in tmux scrolling one of several
side-by-side panels down resulted in all visually scrolling.
Implement the following CSI escape sequences from
https://invisible-island.net/xterm/ctlseqs/ctlseqs.html:
> CSI Ps ; Ps ; Ps t
> [..]
> Ps = 1 4 ⇒ Report xterm text area size in pixels.
> Result is CSI 4 ; height ; width t
> [..]
> Ps = 1 6 ⇒ Report xterm character cell size in pixels.
> Result is CSI 6 ; height ; width t
Extracted from changes in https://github.com/termux/termux-app/pull/2973
by @MatanZ and adopted to play well with the just merged #3098 (.ws_xpixel
and .ws_ypixel values in winsize).
This allows to get terminal size in pixel using `TIOCGWINSZ` ioctl.
Set `.ws_xpixel` using `columns * cell_width` and set `.ws_ypixel` using `rows * cell_height`.
Cell width and height is font width and line spacing, respectively.
- The AutoFill type and hints are no longer hardcoded in `TerminalView` class and `TermuxActivity` layout xml. They are dynamically set to required values before making a manual AutoFill request and reverted back afterwards to default values. The hardcoded value `AUTOFILL_TYPE_TEXT` returned by `getAutofillType()` was causing the AutoFill UI to show on Activity starts, this will return `AUTOFILL_TYPE_NONE` by default now so that AutoFill UI isn't shown automatically.
- The AutoFill importance is no longer hardcoded in `TermuxActivity` layout xml and is returned by `TerminalView` class itself by `getImportantForAutofill()`.
- The AutoFill function in `TermuxActivity` for making a manual AutoFill request is moved to `TerminalView` class. This and moving of hardcoded values to `TerminalView` class mentioned above is done as complete logic of AutoFill should be handled by `TerminalView` class itself and not scattered in various places.
- The Terminal context menu now supports AutoFilling a username. Note that GBoard/Google Password Manager seems to have a bug where it will still show `Pick a saved password` instead of username, even though `AUTOFILL_HINT_USERNAME` is being requested, however it will still AutoFill a username of selected entry correctly.
- Pressing the back button to close the keyboard will also cancel the current manually requested AutoFill request and UI will not show when keyboard is opened again.
Closes#3909
In other terminals, such as gnome-terminal, Shift-PgUp and Shift-PgDn
scroll the screen by a full page, rather than a single line. Adjust
termux to match.
Currently the Termux terminal emulator prints "HI" in red with:
```sh
printf "\e[31;m HI \e[0m"
```
This is not how other terminals (tested on xterm, gnome-terminal,
alacritty and the mac built in terminal) handle it, since they parse
""\e[31;m" as "\e[31;0m", where the "0" resets the colors.
This change aligns with other terminals, as well as improves performance
by avoiding allocating a new int[] array for each byte processed by
`parseArg()`, and most importantly simplifies things by removing the
`mIsCSIStart` and `mLastCSIArg` state, preparing for supporting ':'
separated sub parameters such as used in
https://sw.kovidgoyal.net/kitty/underlines/
This reverts commit 2ac7fd1e56.
Do not use `upload-release-action` for uploading artifacts and generating checksum and instead keep using standard `sha256sum` and internal github tools. `upload-release-action` also generates checksum in the wrong format, check https://github.com/termux/termux-app/pull/3241#discussion_r1106019790.
The exception below causing app crash happens because of malicious input where combining characters keep getting added to same column of the row and this increases the size of `mSpaceUsed` and `mText`, eventually causing a buffer overflow of `mSpaceUsed`, which is limited to max `32767` value as per java `short` limit, but the limit itself isn't the issue, but an endless number of combining characters being added. Check `MAX_COMBINING_CHARACTERS_PER_COLUMN` field javadocs for why the limit `15` was chosen.
```
curl -o matroska.js https://kimapr.net/lappy/matroska.js
cat matroska.js
```
The `charCount` below refers to value of `Character.charCount(codePoint)`, like before `oldCharactersUsedForColumn` is appended to `newCharactersUsedForColumn`.
```
TerminalRow: codePoint=112, mColumns=98, mText=637, columnToSet=18, mSpaceUsed=590, javaCharDifference=0, oldStartOfColumnIndex=510, oldCharactersUsedForColumn=1, newCharactersUsedForColumn=1, oldNextColumnIndex=511, newNextColumnIndex=511, charCount=1, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=1
TerminalRow: codePoint=40, mColumns=98, mText=637, columnToSet=19, mSpaceUsed=590, javaCharDifference=0, oldStartOfColumnIndex=511, oldCharactersUsedForColumn=1, newCharactersUsedForColumn=1, oldNextColumnIndex=512, newNextColumnIndex=512, charCount=1, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=1
TerminalRow: codePoint=40, mColumns=98, mText=637, columnToSet=20, mSpaceUsed=590, javaCharDifference=0, oldStartOfColumnIndex=512, oldCharactersUsedForColumn=1, newCharactersUsedForColumn=1, oldNextColumnIndex=513, newNextColumnIndex=513, charCount=1, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=1
TerminalRow: codePoint=101, mColumns=98, mText=637, columnToSet=21, mSpaceUsed=590, javaCharDifference=0, oldStartOfColumnIndex=513, oldCharactersUsedForColumn=1, newCharactersUsedForColumn=1, oldNextColumnIndex=514, newNextColumnIndex=514, charCount=1, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=1
TerminalRow: codePoint=917772, mColumns=98, mText=147, columnToSet=18, mSpaceUsed=98, javaCharDifference=2, oldStartOfColumnIndex=18, oldCharactersUsedForColumn=1, newCharactersUsedForColumn=3, oldNextColumnIndex=19, newNextColumnIndex=21, charCount=2, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=0
I TerminalRow: codePoint=65024, mColumns=98, mText=147, columnToSet=18, mSpaceUsed=100, javaCharDifference=1, oldStartOfColumnIndex=18, oldCharactersUsedForColumn=3, newCharactersUsedForColumn=4, oldNextColumnIndex=21, newNextColumnIndex=22, charCount=1, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=0
TerminalRow: codePoint=917772, mColumns=98, mText=147, columnToSet=18, mSpaceUsed=101, javaCharDifference=2, oldStartOfColumnIndex=18, oldCharactersUsedForColumn=4, newCharactersUsedForColumn=6, oldNextColumnIndex=22, newNextColumnIndex=24, charCount=2, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=0
...
TerminalRow: codePoint=917959, mColumns=98, mText=32781, columnToSet=18, mSpaceUsed=32763, javaCharDifference=2, oldStartOfColumnIndex=18, oldCharactersUsedForColumn=32666, newCharactersUsedForColumn=32668, oldNextColumnIndex=32684, newNextColumnIndex=32686, charCount=2, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=0
TerminalRow: codePoint=917939, mColumns=98, mText=32781, columnToSet=18, mSpaceUsed=32765, javaCharDifference=2, oldStartOfColumnIndex=18, oldCharactersUsedForColumn=32668, newCharactersUsedForColumn=32670, oldNextColumnIndex=32686, newNextColumnIndex=32688, charCount=2, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=0
TerminalRow: codePoint=917961, mColumns=98, mText=32781, columnToSet=18, mSpaceUsed=32767, javaCharDifference=2, oldStartOfColumnIndex=18, oldCharactersUsedForColumn=32670, newCharactersUsedForColumn=32672, oldNextColumnIndex=32688, newNextColumnIndex=32690, charCount=2, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=0
TerminalRow: codePoint=917804, mColumns=98, mText=32781, columnToSet=18, mSpaceUsed=-32767, javaCharDifference=2, oldStartOfColumnIndex=18, oldCharactersUsedForColumn=1, newCharactersUsedForColumn=3, oldNextColumnIndex=19, newNextColumnIndex=21, charCount=2, oldCodePointDisplayWidth=1, newCodePointDisplayWidth=0
```
```
java.lang.ArrayIndexOutOfBoundsException: src.length=32781 srcPos=19 dst.length=32781 dstPos=21 length=-32786
at java.lang.System.arraycopy(System.java:469)
at com.termux.terminal.TerminalRow.setChar(TerminalRow.java:196)
at com.termux.terminal.TerminalBuffer.setChar(TerminalBuffer.java:455)
at com.termux.terminal.TerminalEmulator.emitCodePoint(TerminalEmulator.java:2380)
at com.termux.terminal.TerminalEmulator.processCodePoint(TerminalEmulator.java:624)
at com.termux.terminal.TerminalEmulator.processByte(TerminalEmulator.java:520)
at com.termux.terminal.TerminalEmulator.append(TerminalEmulator.java:487)
at com.termux.terminal.TerminalSession$MainThreadHandler.handleMessage(TerminalSession.java:358)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7664)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
```
See also following links for history of related changes to `TerminalRow` for combining characters. Note that jackpal terminal does not crash for above, which termux-app is based on, but changes were done by fornwall in initial commit of termux-app to change the behaviour, hence the crash, but he added the `FIXME: Put a limit of combining characters` comment as a note to solve the current issue in future, which is now.
- 9a47042620
- https://github.com/jackpal/Android-Terminal-Emulator/pull/338
- a18ee58f7a (diff-f84d215b18106c037e01986a3968fa54b74691174a78fcc99493f745d3805be5)Closes#3839
The `Docs` refer to "something" that is changed, and not the type of change being made. If docs are to be changed in future, it should be added as a scope instead, like `Added(docs): Add some docs` or `Fixed(docs): Fix some docs`.