HMCL icon indicating copy to clipboard operation
HMCL copied to clipboard

[Bug] 在“从互联网下载整合包”弹窗中输入特殊字符会导致启动器崩溃

Open G-mare opened this issue 1 month ago • 1 comments

问题描述 | Bug Description

复现步骤:

  1. 打开HMCL启动器。
  2. 依次点击“实例列表” -> “安装新整合包” -> “从互联网下载整合包”。
  3. 在弹出的输入框中,仅输入一个特殊字符(例如:")。
  4. 点击“确定”按钮。
  5. 启动器弹出错误弹窗并崩溃

附加信息:

  1. 已测试会导致启动器崩溃的字符:` # % ^ "
  2. 经测试,输入普通字母数字或完整URL没有问题。此Bug在 预览版 HMCL-3.8.dev-94ca810 中仍然存在,崩溃日志与稳定版相同

启动器崩溃报告 / 启动器日志文件 | Launcher Crash Report / Launcher Log File

HMCL v3.8.1 崩溃日志
  Version: 3.8.1
  Time: 2025-12-05 20:13:07
  Thread: Thread[#35,JavaFX Application Thread,5,main]

  Content: 
    java.lang.IllegalArgumentException: Illegal character in path at index 0: "
	at java.base/java.net.URI.create(URI.java:932)
	at org.jackhuang.hmcl.util.io.NetworkUtils.toURI(NetworkUtils.java:415)
	at org.jackhuang.hmcl.task.FileDownloadTask.<init>(FileDownloadTask.java:86)
	at org.jackhuang.hmcl.ui.download.ModpackSelectionPage.lambda$onChooseRemoteFile$4(ModpackSelectionPage.java:146)
	at org.jackhuang.hmcl.ui.construct.InputDialogPane.lambda$new$3(InputDialogPane.java:63)
	at javafx.base@25/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at javafx.base@25/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
	at javafx.base@25/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
	at javafx.base@25/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at javafx.base@25/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.base@25/javafx.event.Event.fireEvent(Event.java:199)
	at javafx.graphics@25/javafx.scene.Node.fireEvent(Node.java:9026)
	at javafx.controls@25/javafx.scene.control.Button.fire(Button.java:203)
	at javafx.controls@25/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:207)
	at javafx.controls@25/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
	at javafx.base@25/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
	at javafx.base@25/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at javafx.base@25/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:232)
	at javafx.base@25/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:189)
	at javafx.base@25/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base@25/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base@25/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at javafx.base@25/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.base@25/javafx.event.Event.fireEvent(Event.java:199)
	at javafx.graphics@25/javafx.scene.Scene$MouseHandler.process(Scene.java:4061)
	at javafx.graphics@25/javafx.scene.Scene.processMouseEvent(Scene.java:1947)
	at javafx.graphics@25/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2784)
	at javafx.graphics@25/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.get(GlassViewEventHandler.java:353)
	at javafx.graphics@25/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.get(GlassViewEventHandler.java:255)
	at javafx.graphics@25/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
	at javafx.graphics@25/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
	at javafx.graphics@25/com.sun.glass.ui.View.handleMouseEvent(View.java:573)
	at javafx.graphics@25/com.sun.glass.ui.View.notifyMouse(View.java:975)
	at javafx.graphics@25/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at javafx.graphics@25/com.sun.glass.ui.win.WinApplication.lambda$runLoop$0(WinApplication.java:168)
	at java.base/java.lang.Thread.run(Thread.java:1447)
Caused by: java.net.URISyntaxException: Illegal character in path at index 0: "
	at java.base/java.net.URI$Parser.fail(URI.java:2995)
	at java.base/java.net.URI$Parser.checkChars(URI.java:3166)
	at java.base/java.net.URI$Parser.parseHierarchical(URI.java:3248)
	at java.base/java.net.URI$Parser.parse(URI.java:3207)
	at java.base/java.net.URI.<init>(URI.java:645)
	at java.base/java.net.URI.create(URI.java:930)
	... 75 more


-- System Details --
  Operating System: Windows 10 22H2 10.0.19045.6575
  System Architecture: x86-64
  Java Architecture: x86-64
  Java Version: 24.0.2, Oracle Corporation
  Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode, sharing), Oracle Corporation
  JVM Max Memory: 4263510016
  JVM Total Memory: 79691776
  JVM Free Memory: 35047488

2025-12-05T20-01-46.log 2025-12-05T20-12-51.log

G-mare avatar Dec 05 '25 12:12 G-mare

自己测试了一下,丢了一个关键信息:java.net.URISyntaxException

查了一下,URI 规范(RFC 3986),以下内容可以被接受后^1: 1、英文字母(a-zA-Z) 2、数字(0-9) 3、-_.~ 4 个特殊字符 4、所有保留字符:!*'();:@&=+$,/?#[]

其余字符都要百分号编码

造成此问题的可能性为 HMCL 未正确百分号编码例如 ^ 属于 ASCII 但对 URI 而言非法字符,Java 会严格按照 URI 规范进行处理,因此哪怕你输入的是 https://^ 也会崩溃。冒号、井号等虽然合法但它在错误的位置,也会导致问题

我后面测试了一下同样需要百分号编码的汉字,却没有这个问题,询问了一下 AI 说明 Java 会特殊处理这类非 ASCII 字符

这样看就能解释通为啥数字啥的和非 ASCII 字符不会出问题,而上述列举的几个字符会报错

非专业解释,仅供参考,实际情况可能远比我说的复杂


考虑到出问题的代码被多次个场合使用,虽然可以被手动触发的地方很少,但反映的问题其实较为严重,任何 URI 输入的失误都有可能触发问题,建议尽早处理

WhatDamon avatar Dec 05 '25 14:12 WhatDamon