Skip to content
This repository has been archived by the owner. It is now read-only.

java.lang.StringIndexOutOfBoundsException when try access.downloadFilesAsStream on empty input #298

Closed
greenhost87 opened this issue Nov 25, 2019 · 0 comments

Comments

@greenhost87
Copy link
Collaborator

If you try to use access.downloadFilesAsStream when no file is selected you got:

java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 0
	at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3720)
	at java.base/java.lang.String.substring(String.java:1909)
	at korolev.server.package$$anonfun$1.$anonfun$applyOrElse$14(package.scala:304)
	at scala.collection.ArrayOps$.map$extension(ArrayOps.scala:924)
	at korolev.server.package$$anonfun$1.$anonfun$applyOrElse$13(package.scala:302)
	at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:430)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1425)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1016)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1665)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1598)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)

In my opinion current problem with that code: https://github.com/fomkin/korolev/blob/master/server/base/src/main/scala/korolev/server/package.scala#L300-L306

case Request(Root / "bridge" / deviceId / sessionId / "file" / descriptor / "info", _, _, _, body) =>
        sessions.get(makeSessionKey(deviceId, sessionId)) match {
          case Some(session) =>
            Async[F].map(body.toStrictUtf8) { info =>
              val files = info
                .split("\n")
                .map { entry =>
                  val slash = entry.lastIndexOf('/')
                  (entry.substring(0, slash), entry.substring(slash + 1).toLong)
                }
                .toMap
              session.fileDownloadInfo(descriptor, files)
              Response.Http(Response.Status.Ok, None)
            }
          case None =>
            Async[F].delay(Response.Http(Response.Status.BadRequest, "Session doesn't exist"))
        }

Calling connection.send(Procedure.UploadFiles.code, id.mkString, descriptor) initiate uploading process, but if no files are selected body inside POST /bridge/:deviceId/:sessionId/file/:descriptor/info/:body is empty, as a result Korolev attempt to execute entry.substring(0, -1) and fails without any human friendly error.
My suggestion is, change code as shown below:

case Request(Root / "bridge" / deviceId / sessionId / "file" / descriptor / "info", _, _, _, body) =>
        sessions.get(makeSessionKey(deviceId, sessionId)) match {
          case Some(session) =>
            Async[F].map(body.toStrictUtf8) { info =>
              val files = info
                .split("\n")
                .flatMap {
                  case entry if entry.isBlank =>
                    None
                  case entry =>
                    val slash = entry.lastIndexOf('/')
                    Some((entry.substring(0, slash), entry.substring(slash + 1).toLong))
                }
                .toMap
              session.fileDownloadInfo(descriptor, files)
              Response.Http(Response.Status.Ok, None)
            }
          case None =>
            Async[F].delay(Response.Http(Response.Status.BadRequest, "Session doesn't exist"))
        }
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant