[2.x] fix: Constrain job id parser to signed longs (#9353)

Job ids are long. The job id parser currently uses NotSpace to parse the ids, which fails with a NumberFormatException for short non-numeric values and OOMs SBT for long non-numeric values.
This commit is contained in:
Merlin Hughes 2026-06-27 00:15:43 -04:00 committed by GitHub
parent b1392daa60
commit aa0cb95c48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 14 additions and 9 deletions

View File

@ -112,8 +112,8 @@ See also [Development environment][02] and [Coding style and best practices][03]
sbt features a testing infrastructure encompassing multiple testing methodologies designed to ensure reliability and functionality across different integrations. The testing framework includes:
- [Unit tests][04]
- [scripted tests][05]
- [Manual tests][06], using the locally baked sbt
- [Scripted tests][05]
- [Manual tests][06], which details how to run the locally baked sbt in your own project
### Tech stack

View File

@ -224,13 +224,18 @@ trait Parsers {
lazy val Port = token(IntBasic, "<port>")
/** Parses a signed integer. */
lazy val IntBasic = mapOrFail('-'.? ~ Digit.+)(Function.tupled(toInt))
lazy val IntBasic = parseSigned(_.toInt)
/** Parses a signed long. */
lazy val LongBasic = parseSigned(_.toLong)
/** Parses an unsigned integer. */
lazy val NatBasic = mapOrFail(Digit.+)(_.mkString.toInt)
private def toInt(neg: Option[Char], digits: Seq[Char]): Int =
(neg.toSeq ++ digits).mkString.toInt
private def parseSigned[A](f: String => A) =
mapOrFail('-'.? ~ Digit.+) { case (neg, digits) =>
f((neg.toSeq ++ digits).mkString)
}
/** Parses the lower-case values `true` and `false` into their corresponding Boolean values. */
lazy val Bool = ("true" ^^^ true) | ("false" ^^^ false)

View File

@ -96,12 +96,12 @@ object BackgroundJobService {
private[sbt] def jobIdParser: (State, Seq[JobHandle]) => Parser[Seq[JobHandle]] = {
import DefaultParsers.*
(state, handles) => {
val stringIdParser: Parser[Seq[String]] = Space ~> token(
NotSpace.examples(handles.map(_.id.toString).toSet),
val idParser: Parser[Seq[Long]] = Space ~> token(
LongBasic.examples(handles.map(_.id.toString).toSet),
description = "<job id>"
).+
stringIdParser.map { strings =>
strings.map(Integer.parseInt(_)).flatMap(id => handles.find(_.id == id))
idParser.map { ids =>
ids.flatMap(id => handles.find(_.id == id))
}
}
}