PackageTrack
Sign in Get early access

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 2026
Release Pre-release

Releases

latest 5
  1. 0.4.2 14 Aug 2026
    Release notes

    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

    Open source →
    Release notes
    • Fix 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, and UBSan confirmed it on two reachable paths: <release timestamp="999..."> overflowing long long, and <icon width="999..."> overflowing int. Both values come from an attribute in a catalog fetched over the network. The same helper also feeds priority, 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_r return value in unixEpochToISO8601. It returns null for a time_t it cannot represent, which a saturated epoch reaches; ignoring it left the std::tm zero-initialized and silently produced a 1900-01-01T00:00:00Z timestamp. An unrepresentable epoch now yields no timestamp.
    • Add scripts/tidy.sh, pinning clang-tidy the way scripts/format.sh pins 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 on PATH: the version CI installed could not parse a current libstdc++ and bailed early, while also emitting a bugprone-use-after-move false positive on x = {} immediately after std::move(x). The pinned version is what found the gmtime_r defect above.
    Open source →
  2. 0.4.1 14 Aug 2026
    Release notes

    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/bundle

    Note 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

    Open source →
    Release notes
    • Restore Flutter compatibility, which 0.4.0 broke. hooks ^2.1.0 requires meta ^1.19.0, but flutter_test from the Flutter SDK pins meta 1.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 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 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 @Native externals against @DefaultAsset instead of resolving them through DynamicLibrary.open. hook/build.dart already emitted the library as a code asset, but the VM consults its asset table only for @Native declarations, 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/maps scan, a glob through .dart_tool/hooks_runner/ internals, and candidate paths derived from Platform.script, the executable, and the current directory. The last of those made the process load libappstream.so from a CWD-relative lib/, build/, or src/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.dart and lib/src/appstream_native.dart, which described the @Native mechanism 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-rename appstream/ and listed a dart_api_dl.c that is now .cpp, and the prerequisites claimed Clang 17+ while the std::expected polyfill targets Clang 18.
    Open source →
  3. 0.4.0 14 Aug 2026
    Release notes

    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.sh never built the C++ suite. It passed -DBUILD_TESTING=ON, but the gate has been -DAPPSTREAM_BUILD_TESTS=ON since 0.2.2. CMake was warning Manually-specified variables were not used by the project, and ctest silently 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 AppStreamParser and XmlScanner, all semantics-preserving: explicit parentheses in mixed */+ accumulator arithmetic, contains() in place of a find() != npos membership test, and consistent braces across the provides if/else chain. No bugprone-*, cert-*, clang-analyzer-*, or performance-* 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

    Open source →
    Release notes
    • 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. The build hook API is unchanged between hooks 1.x and 2.x, so hook/build.dart needed no edits and the public Dart API is untouched; the bump also unpins native_toolchain_c and record_use from their 1.x-era versions. The SDK constraint stays ^3.10.0.
    • Repository moved to github.com/flatpak-minimal/appstream_dart; repository and issue_tracker updated to match.
    • Fix scripts/test.sh passing -DBUILD_TESTING=ON, which the CMake build ignores — the gate has been -DAPPSTREAM_BUILD_TESTS=ON since 0.2.2. The C++ suite was therefore never configured or rebuilt, and ctest silently 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 AppStreamParser and XmlScanner: explicit parentheses in mixed */+ accumulator arithmetic, contains() in place of a find() != npos membership test, and consistent braces across the provides if/else chain.
    Open source →
  4. 0.3.0 13 Apr 2026
    Release notes

    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]

    Open source →
    Release notes
    • Licensing: adopt SPDX license headers (SPDX-License-Identifier / SPDX-FileCopyrightText) across all source files; add THIRD_PARTY_LICENSES cataloging 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, and lib/src/database/tables.dart.
    Open source →
  5. 0.2.2 08 Apr 2026
    Release notes
    • pub.dev publishing hygiene:
      • Add lib/appstream_dart.dart re-export so the primary library name matches the package name. The original lib/appstream.dart import continues to work.
      • Rename docs/doc/ and tests/native_tests/ to match the pub package layout (singular doc/, no clash with the Dart test/ directory).
      • Add .pubignore to keep build artifacts, the cached appstream.xml/catalog.db, the Flutter example sub-package, and legacy/dev shell scripts out of the published archive.
    • Native build: gate the C++ test suite behind -DAPPSTREAM_BUILD_TESTS=ON so the package:hooks build 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::~SqliteWriter noexcept and wrap its body in a try/catch so a logging failure during teardown can no longer std::terminate the 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 to open(2)/SQLite with no normalization or sandboxing, so callers accepting them from untrusted input must validate first.
    • Tooling: add .clang-format and .clang-tidy at the repo root so formatting and lint runs are deterministic.
    • Flutter example (example/flathub_catalog): drive the package's CMake build via ExternalProject_Add so libappstream.so is always built and bundled before the runner is linked.
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive