mirror of
https://github.com/apple/container.git
synced 2026-08-24 10:05:43 -05:00
fix: clamp ProgressBar barLength to non-negative value to avoid crash (#1525)
- Closes #1547. - A negative progress value (e.g. from a race in progress events) would produce a negative barLength and crash inside String(repeating:count:). Wrap the computed length in max(0, ...) and add a regression test that calls set(size: -10) and exercises draw(state:detail:).
This commit is contained in:
@@ -275,7 +275,7 @@ extension ProgressBar {
|
||||
// 45 reserves space for components rendered after the bar (size, speed, time, etc.)
|
||||
let usedWidth = (useColor ? joinedComponents.visibleLength : joinedComponents.count) + 45
|
||||
let remainingWidth = max(config.width - usedWidth, 1)
|
||||
let barLength = min(remainingWidth, state.finished ? remainingWidth : Int(Int64(remainingWidth) * value / total))
|
||||
let barLength = min(remainingWidth, max(0, state.finished ? remainingWidth : Int(Int64(remainingWidth) * value / total)))
|
||||
let barPaddingLength = remainingWidth - barLength
|
||||
if useColor {
|
||||
let filledBar = EscapeSequence.colored(String(repeating: config.theme.bar, count: barLength), EscapeSequence.green)
|
||||
|
||||
@@ -749,6 +749,22 @@ final class ProgressBarTests: XCTestCase {
|
||||
let _ = progress.draw()
|
||||
}
|
||||
|
||||
func testProgressBarNegativeValue() async throws {
|
||||
// Regression test: a negative progress value (e.g. from a race in progress events)
|
||||
// must not cause String(repeating:count:) to be called with a negative count.
|
||||
let config = try ProgressConfig(
|
||||
description: "Task",
|
||||
showProgressBar: true,
|
||||
totalSize: 50,
|
||||
width: 57
|
||||
)
|
||||
let progress = ProgressBar(config: config)
|
||||
progress.set(size: -10)
|
||||
// draw(state:detail:) should clamp barLength to [0, remainingWidth] and not crash.
|
||||
let state = progress.state.withLock { $0 }
|
||||
let _ = progress.draw(state: state, detail: .full)
|
||||
}
|
||||
|
||||
func testItemsName() async throws {
|
||||
let config = try ProgressConfig(
|
||||
description: "Task",
|
||||
|
||||
Reference in New Issue
Block a user