appstream_dart
High-performance AppStream XML parser with C++23 FFI bridge. Streams catalog metadata into SQLite with Drift ORM and FTS5 search.
0.4.2
214 downloads/mo
#1260 most downloaded on pub.dev
flatpak-minimal/appstream_dart
What this package is like to depend on
Last release 9 days ago
14 Aug 2026
Too new to tell
only 2 release windows
Nearly every release is documented
notes for 5 of 5 stable releases
Nothing withdrawn
no release was ever pulled
4 months old
5 releases · first in 2026
5 releases in the last 12 months
see the full history below
Release timeline
5 releases · Apr 2026 to Aug 2026Releases
latest 5-
0.4.214 Aug 2026Release notes
Open source →Security and reliability fix. Recommended for all users. pana 160/160.
Undefined behavior parsing untrusted catalog data
The digit accumulators in
AppStreamParsercomputedresult * 10 + digitwith 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 parsespriority, 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_rgmtime_rreturns null for atime_tit cannot represent, which a saturated epoch reaches. The return value was ignored, leaving thestd::tmzero-initialized and silently producing a1900-01-01T00:00:00Ztimestamp. An unrepresentable epoch now yields no timestamp.Pinned static analysis
scripts/tidy.shpins clang-tidy the wayscripts/format.shpins 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 abugprone-use-after-movefalse positive onx = {}immediately afterstd::move(x), which is the documented way to restore a moved-from object. The pinned version is what found thegmtime_rdefect above.Version Parses host libstdc++ use-after-movefalse positiveFound gmtime_rdefect18 ✗ bails early yes no 20 (pinned) ✓ no ✓ 22 ✓ no no The gate passes
--warnings-as-errors, because plainclang-tidyexits 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-infosclean,dart pub publish --dry-run0 warnings.No API changes.
Full changelog: https://github.com/flatpak-minimal/appstream_dart/blob/v0.4.2/CHANGELOG.md
Release notes
Open source →- Fix undefined behavior parsing untrusted catalog data. The digit
accumulators in
AppStreamParsercomputedresult * 10 + digitwith no bound, so a long enough run of digits overflowed. Signed overflow is undefined behavior, and UBSan confirmed it on two reachable paths:<release timestamp="999...">overflowinglong long, and<icon width="999...">overflowingint. Both values come from an attribute in a catalog fetched over the network. The same helper also feedspriority, image and video dimensions, and icon scale. Accumulation now saturates, so a hostile value is clamped rather than wrapped. Regression tests cover both inputs. - Check the
gmtime_rreturn value inunixEpochToISO8601. It returns null for atime_tit cannot represent, which a saturated epoch reaches; ignoring it left thestd::tmzero-initialized and silently produced a1900-01-01T00:00:00Ztimestamp. An unrepresentable epoch now yields no timestamp. - Add
scripts/tidy.sh, pinning clang-tidy the wayscripts/format.shpins clang-format, and make the CI clang-tidy job blocking rather than advisory. The unpinned checker gave results that depended on which LLVM happened to be first onPATH: the version CI installed could not parse a current libstdc++ and bailed early, while also emitting abugprone-use-after-movefalse positive onx = {}immediately afterstd::move(x). The pinned version is what found thegmtime_rdefect above.
- Fix undefined behavior parsing untrusted catalog data. The digit
accumulators in
-
0.4.114 Aug 2026Release notes
Open source →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 failedEvery Flutter app depends on
flutter_test, so no Flutter project on an SDK pinningmeta1.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'andcode_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.dartpublishedlibappstream.soas a code asset, but the Dart VM consults its asset table only for@Nativedeclarations — a plainDynamicLibrary.open(name)never sees it. The asset was therefore built and never used, andbindings.dartcompensated with a seven-step runtime search.Symbols are now
@Nativeexternals bound to@DefaultAsset, and that search is gone (~180 lines): a/proc/self/mapsscan, a glob through.dart_tool/hooks_runner/internals, and candidates derived fromPlatform.script, the executable, and the current directory.Security: those CWD-relative candidates meant the process would load
libappstream.sofrom./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 —
AppstreamBindingsis not exported.Deployment note
Resolution goes through
NativeAssetsManifest.json, which maps the asset to the plain sonamelibappstream.so, so the finaldlopenuses the system loader. The standard Flutter Linux runner setsRPATH=$ORIGIN/liband bundles the library, so it just works. Embedders whose binary lives outside the bundle (ivi-homescreen, for example) need it onLD_LIBRARY_PATH:LD_LIBRARY_PATH=/path/to/bundle/lib homescreen -b /path/to/bundle
Note that
flutter build bundledoes not perform Linux native-asset packaging — useflutter 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
@Nativevs 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-infosclean,dart pub publish --dry-run0 warnings.Full changelog: https://github.com/flatpak-minimal/appstream_dart/blob/v0.4.1/CHANGELOG.md
Release notes
Open source →- Restore Flutter compatibility, which 0.4.0 broke.
hooks^2.1.0 requiresmeta^1.19.0, butflutter_testfrom the Flutter SDK pinsmeta1.18.0 on 3.44.x, so any Flutter app failed version solving against appstream_dart 0.4.0 — the bundled example included. The constraints are nowhooks: '>=1.0.2 <3.0.0'andcode_assets: '>=1.0.0 <2.0.0', which resolve to 2.1.0/1.2.1 standalone and to 1.0.2/1.0.0 under an older Flutter. The build hook is source-compatible with both majors. - Bind the native symbols as
@Nativeexternals against@DefaultAssetinstead of resolving them throughDynamicLibrary.open.hook/build.dartalready emitted the library as a code asset, but the VM consults its asset table only for@Nativedeclarations, so that asset was built and then never used; the loader compensated with a seven-step search. The public API is unchanged. - Remove that search chain (~180 lines): a
/proc/self/mapsscan, a glob through.dart_tool/hooks_runner/internals, and candidate paths derived fromPlatform.script, the executable, and the current directory. The last of those made the process loadlibappstream.sofrom a CWD-relativelib/,build/, orsrc/build/directory, so running an application from a directory an attacker could write to was enough to get a library of their choosing loaded. - Correct the comments in
hook/build.dartandlib/src/appstream_native.dart, which described the@Nativemechanism that did not yet exist. - Refresh stale facts in the README, which is the pub.dev landing page: the
install snippet advertised
^0.2.2, the status line and test count were three releases old (194 tests, not 185), the project tree was rooted at the pre-renameappstream/and listed adart_api_dl.cthat is now.cpp, and the prerequisites claimed Clang 17+ while thestd::expectedpolyfill targets Clang 18.
-
0.4.014 Aug 2026Release notes
Open source →First release from
flatpak-minimal/appstream_dart. Scores 160/160 on pana.Breaking (dependency resolution)
hooks^1.0.2 → ^2.1.0 andcode_assets^1.0.0 → ^1.2.1. Consumers pinned tohooks1.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
hooksmajor bump, sohook/build.dartneeded no edits, and the SDK constraint stays^3.10.0. The old bound was pinningcode_assetsto 1.0.0 and holdingnative_toolchain_candrecord_useat 1.x-era versions.Repository move
repositoryandissue_trackernow point atgithub.com/flatpak-minimal/appstream_dart. The previously published 0.3.0 still advertises the oldmeta-flutter/appstreamURL 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-infosclean, both format gates clean against CI's toolchain, 149/149 C++ tests (including asan and ubsan), 45/45 Dart tests,dart pub publish --dry-runreports 0 warnings.Full changelog: https://github.com/flatpak-minimal/appstream_dart/blob/v0.4.0/CHANGELOG.md
Release notes
Open source →- Breaking (dependency resolution):
hooks^1.0.2 → ^2.1.0 andcode_assets^1.0.0 → ^1.2.1. Consumers pinned tohooks1.x will no longer resolve. The build hook API is unchanged betweenhooks1.x and 2.x, sohook/build.dartneeded no edits and the public Dart API is untouched; the bump also unpinsnative_toolchain_candrecord_usefrom their 1.x-era versions. The SDK constraint stays^3.10.0. - Repository moved to
github.com/flatpak-minimal/appstream_dart;repositoryandissue_trackerupdated to match. - Fix
scripts/test.shpassing-DBUILD_TESTING=ON, which the CMake build ignores — the gate has been-DAPPSTREAM_BUILD_TESTS=ONsince 0.2.2. The C++ suite was therefore never configured or rebuilt, andctestsilently ran whatever stale binary was left in the build directory. CI already passed the correct flag, so only local runs were affected. - clang-tidy cleanups in
AppStreamParserandXmlScanner: explicit parentheses in mixed*/+accumulator arithmetic,contains()in place of afind() != nposmembership test, and consistent braces across theprovidesif/else chain.
-
0.3.013 Apr 2026Release notes
Open source →Bump version to 0.3.0 and add changelog entry covering:
- SPDX license headers and THIRD_PARTY_LICENSES
- sqlite3 ^3.3.1, lints ^6.1.0
- Dartdoc comments on all exported API surfaces
Signed-off-by: Joel Winarske [email protected]
Release notes
Open source →- Licensing: adopt SPDX license headers (
SPDX-License-Identifier/SPDX-FileCopyrightText) across all source files; addTHIRD_PARTY_LICENSEScataloging every direct dependency. - LICENSE file replaced with the compact SPDX-standard Apache-2.0 text.
- Dependency bumps:
sqlite3^2.4.0 → ^3.3.1,lints^4.0.0 → ^6.1.0 (applies to both the main package and the Flutter example). - Public API documentation: add dartdoc comments to all exported classes,
fields, and constructors in
lib/appstream.dart,lib/src/database/database.dart, andlib/src/database/tables.dart.
-
0.2.208 Apr 2026Release notes
Open source →- pub.dev publishing hygiene:
- Add
lib/appstream_dart.dartre-export so the primary library name matches the package name. The originallib/appstream.dartimport continues to work. - Rename
docs/→doc/andtests/→native_tests/to match the pub package layout (singulardoc/, no clash with the Darttest/directory). - Add
.pubignoreto keep build artifacts, the cachedappstream.xml/catalog.db, the Flutter example sub-package, and legacy/dev shell scripts out of the published archive.
- Add
- Native build: gate the C++ test suite behind
-DAPPSTREAM_BUILD_TESTS=ONso thepackage:hooksbuild hook and downstream consumers no longer fetch GoogleTest or build the test executable by default. - Reliability and security fixes surfaced by clang-tidy:
- Fix 8 use-after-move bugs in
AppStreamParser(member key strings were re-checked via.empty()after being moved). - Mark
SqliteWriter::~SqliteWriternoexceptand wrap its body in a try/catch so a logging failure during teardown can no longerstd::terminatethe parsing process. postString(FFI) now returns success/failure and a stack-allocated OOM sentinel (-2) is posted if the malloc fails, instead of the progress message being silently dropped.- Document path-handling expectations on
appstream_parse_to_sqlite: paths are passed directly toopen(2)/SQLite with no normalization or sandboxing, so callers accepting them from untrusted input must validate first.
- Fix 8 use-after-move bugs in
- Tooling: add
.clang-formatand.clang-tidyat the repo root so formatting and lint runs are deterministic. - Flutter example (
example/flathub_catalog): drive the package's CMake build viaExternalProject_Addsolibappstream.sois always built and bundled before the runner is linked.
- pub.dev publishing hygiene: