Releases: flatpak-minimal/appstream_dart
Release list
v0.4.2
Security and reliability fix. Recommended for all users. pana 160/160.
Undefined behavior parsing untrusted catalog data
The digit accumulators in AppStreamParser computed result * 10 + digit with no bound, so a long enough run of digits overflowed. Signed overflow is undefined behavior. UBSan confirmed it on the real code path:
AppStreamParser.cpp:57 runtime error: signed integer overflow:
999999999999999999 * 10 cannot be represented in type 'long long int'
AppStreamParser.cpp:37 runtime error: signed integer overflow:
999999999 * 10 cannot be represented in type 'int'
Both are reached from attribute values in a catalog downloaded over the network — <release timestamp="999…"> and <icon width="999…">. The same helper also parses priority, image and video dimensions, and icon scale.
Accumulation now saturates, so a hostile value is clamped rather than wrapped, and the parse stays total. Three regression tests cover it.
This was not caught earlier despite CI running a Debug/Release x asan/ubsan matrix, because no test fed an oversized number.
Unchecked gmtime_r
gmtime_r returns null for a time_t it cannot represent, which a saturated epoch reaches. The return value was ignored, leaving the std::tm zero-initialized and silently producing a 1900-01-01T00:00:00Z timestamp. An unrepresentable epoch now yields no timestamp.
Pinned static analysis
scripts/tidy.sh pins clang-tidy the way scripts/format.sh pins clang-format, and the CI clang-tidy job is no longer advisory.
Unpinned, results depended on which LLVM happened to be first on PATH. The version CI installed could not parse a current libstdc++ — it emitted 20 parse errors and stopped early — while also reporting a bugprone-use-after-move false positive on x = {} immediately after std::move(x), which is the documented way to restore a moved-from object. The pinned version is what found the gmtime_r defect above.
| Version | Parses host libstdc++ | use-after-move false positive |
Found gmtime_r defect |
|---|---|---|---|
| 18 | ✗ bails early | yes | no |
| 20 (pinned) | ✓ | no | ✓ |
| 22 | ✓ | no | no |
The gate passes --warnings-as-errors, because plain clang-tidy exits 0 even when it reports diagnostics.
Verification
152/152 C++ tests (three new) including asan and ubsan, 45/45 Dart, UBSan clean on both hostile inputs after the fix, clang-tidy clean at the pinned version, clang-format applied last, dart analyze --fatal-infos clean, dart pub publish --dry-run 0 warnings.
No API changes.
Full changelog: https://github.com/flatpak-minimal/appstream_dart/blob/v0.4.2/CHANGELOG.md
v0.4.1
Recommended upgrade for all users, required for Flutter users. pana 160/160.
Fixes a regression that made 0.4.0 unusable from Flutter
hooks >=2.1.0 depends on meta ^1.19.0
flutter_test from sdk depends on meta 1.18.0
→ version solving failed
Every Flutter app depends on flutter_test, so no Flutter project on an SDK pinning meta 1.18.0 (3.44.x) could depend on appstream_dart 0.4.0 at all. The bundled example was one of them, which is how this surfaced. CI had missed it because its Flutter job runs 3.47.0.
Constraints are now hooks: '>=1.0.2 <3.0.0' and code_assets: '>=1.0.0 <2.0.0', which resolve to 2.1.0/1.2.1 standalone and 1.0.2/1.0.0 under an older Flutter. The build hook is source-compatible with both majors, so the pana score is unaffected.
Native symbols now resolve through the asset table
hook/build.dart published libappstream.so as a code asset, but the Dart VM consults its asset table only for @Native declarations — a plain DynamicLibrary.open(name) never sees it. The asset was therefore built and never used, and bindings.dart compensated with a seven-step runtime search.
Symbols are now @Native externals bound to @DefaultAsset, and that search is gone (~180 lines): a /proc/self/maps scan, a glob through .dart_tool/hooks_runner/ internals, and candidates derived from Platform.script, the executable, and the current directory.
Security: those CWD-relative candidates meant the process would load libappstream.so from ./lib, ./build, or ./src/build. Running an application from a directory an attacker can write to was enough to get a library of their choosing loaded.
The public API is unchanged — AppstreamBindings is not exported.
Deployment note
Resolution goes through NativeAssetsManifest.json, which maps the asset to the plain soname libappstream.so, so the final dlopen uses the system loader. The standard Flutter Linux runner sets RPATH=$ORIGIN/lib and bundles the library, so it just works. Embedders whose binary lives outside the bundle (ivi-homescreen, for example) need it on LD_LIBRARY_PATH:
LD_LIBRARY_PATH=/path/to/bundle/lib homescreen -b /path/to/bundleNote that flutter build bundle does not perform Linux native-asset packaging — use flutter build linux. The README documents this.
Verification
Exercised on three runtimes against the real 48 MB Flathub catalog:
dart run/dart test— 45/45- Flutter example under GTK on Wayland — full import, 4677 components, 319 languages
- Same example on ivi-homescreen on Wayland — same result
Throughput is unchanged (416/411 ms with @Native vs 414/409 ms before): the FFI boundary is crossed twice per parse and components stream over the Dart port, so the binding mechanism cannot move it.
149/149 C++ tests (including asan and ubsan), 45/45 Dart, clang-tidy clean, dart analyze --fatal-infos clean, dart pub publish --dry-run 0 warnings.
Full changelog: https://github.com/flatpak-minimal/appstream_dart/blob/v0.4.1/CHANGELOG.md
v0.4.0
First release from flatpak-minimal/appstream_dart. Scores 160/160 on pana.
Breaking (dependency resolution)
hooks ^1.0.2 → ^2.1.0 and code_assets ^1.0.0 → ^1.2.1. Consumers pinned to hooks 1.x will no longer resolve. This is why the release is 0.4.0 rather than 0.3.1 — in 0.x semver a breaking change bumps the minor.
The public Dart API is unchanged. The build hook API is identical across the hooks major bump, so hook/build.dart needed no edits, and the SDK constraint stays ^3.10.0. The old bound was pinning code_assets to 1.0.0 and holding native_toolchain_c and record_use at 1.x-era versions.
Repository move
repository and issue_tracker now point at github.com/flatpak-minimal/appstream_dart. The previously published 0.3.0 still advertises the old meta-flutter/appstream URL on pub.dev; this release corrects the listing.
Fixes
scripts/test.shnever built the C++ suite. It passed-DBUILD_TESTING=ON, but the gate has been-DAPPSTREAM_BUILD_TESTS=ONsince 0.2.2. CMake was warningManually-specified variables were not used by the project, andctestsilently ran whatever stale binary was left in the build directory — locally, one still linked against a since-removed gtest 1.15.2. CI already passed the correct flag, so only local runs were affected.- clang-tidy cleanups in
AppStreamParserandXmlScanner, all semantics-preserving: explicit parentheses in mixed*/+accumulator arithmetic,contains()in place of afind() != nposmembership test, and consistent braces across theprovidesif/else chain. Nobugprone-*,cert-*,clang-analyzer-*, orperformance-*findings.
Verification
dart analyze --fatal-infos clean, both format gates clean against CI's toolchain, 149/149 C++ tests (including asan and ubsan), 45/45 Dart tests, dart pub publish --dry-run reports 0 warnings.
Full changelog: https://github.com/flatpak-minimal/appstream_dart/blob/v0.4.0/CHANGELOG.md