uttrflow / uttrflow/uttrflow-swift

A config.json group_size of 0 crashes the suggestion model load with a division by zero

Open Beginner friendly
#696 0 comments 0 reactions 0 assignees View on GitHub
area:ai-suggestions bug good first issue P2
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

`QuantizedLayerPlan.shapes` divides by the group size read from the model's `config.json`, and nothing checks that value first:

```swift
// Sources/UttrflowLocalModel/QuantizedLayerPlan.swift:63-64
static func shapes(rows: Int, columns: Int, groupSize: Int, bits: Int) -> (weight: [Int], scales: [Int]) {
([rows, columns * bits / 32], [rows, columns / groupSize])
}
```

`QuantizedLoad.build` passes `groupSize` straight from `BaseConfiguration.PerLayerQuantization` (`Sources/UttrflowLocalModel/QuantizedLoad.swift:36-41`). That type decodes `group_size` as a plain `Int` with no range check (mlx-swift-lm `Libraries/MLXLMCommon/BaseConfiguration.swift:28-34, 52`). A cached model whose `config.json` says `"group_size": 0`, globally or for any one layer whose safetensors header has `.scales`, hits Swift's integer division by zero. That traps and takes the app down. It happens when AI suggestions or the local clean-up model load (`MLXCandidateScorer.swift:95`, `MLXCleanupModel.swift:36`), and again on every later load while the file stays in the cache. A negative value gives a negative placeholder shape instead.

This is the same class as #441, which was a safetensors header value trusted into arithmetic. `config.json` comes from the hub download, which is not pinned (#666).

## Why it matters

A bad or tampered model file should give "the model could not be loaded", not a crash that repeats each time the person types, until they find and delete a hidden cache folder.

## How to reproduce

In a copy of a cached suggestion model snapshot, set `quantization.group_size` in `config.json` to `0` and point a load at it (for example a test calling `QuantizedLoad.container(from:using:)`). The process traps in `QuantizedLayerPlan.shapes`.

## Acceptance criteria

- `QuantizedLoad.build` (or `shapes`) accepts a layer only when `groupSize > 0`, `bits` is one MLX supports, and `columns` is divisible by `groupSize`. Otherwise it throws, or skips the placeholder build so the ordinary load reports the error. It never traps.
- A test in `Tests/UttrflowLocalModelTests/QuantizedLayerPlanTests.swift` covers `group_size` 0 and a negative value.

## Where to start

- `Sources/UttrflowLocalModel/QuantizedLoad.swift` and `QuantizedLayerPlan.swift`
- Extend `Tests/UttrflowLocalModelTests/QuantizedLayerPlanTests.swift`
- Run `make verify`. See `CONTRIBUTING.md`.

Size: small (under 30 lines plus tests).

Contributor guide

Open the contributing guide

Research direction

Start with Sources/UttrflowLocalModel/QuantizedLoad.swift and QuantizedLayerPlan.swift, especially the group-size handling and shapes calculation. Extend Tests/UttrflowLocalModelTests/QuantizedLayerPlanTests.swift for zero and negative group_size values, then run make verify. Done means invalid configuration values produce a load error rather than a process trap.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
machine-learning
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.