lib/transaction_store.c: store a copy in transaction packages array

This fixes multiple use after frees, found with AddressSanitizers.

* xbps_package_register: the pkgdb dictionary is replaced with
  the new one.
* xbps_pkgdb_update: here the pkgdb is externalized, freed and
  internalized.
This commit is contained in:
Duncan Overbruck 2020-02-10 00:20:13 +01:00
parent 3eed9bca59
commit dca2223cb7
No known key found for this signature in database
GPG Key ID: 335C1D17EC3D6E35

View File

@ -32,21 +32,25 @@
int HIDDEN int HIDDEN
xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs,
xbps_dictionary_t pkgd, const char *tract, bool autoinst) xbps_dictionary_t pkgrd, const char *tract, bool autoinst)
{ {
xbps_dictionary_t pkgd;
xbps_array_t replaces; xbps_array_t replaces;
const char *pkgver, *repo; const char *pkgver, *repo;
char pkgname[XBPS_NAME_SIZE], *self_replaced; char pkgname[XBPS_NAME_SIZE], *self_replaced;
xbps_dictionary_get_cstring_nocopy(pkgd, "repository", &repo); xbps_dictionary_get_cstring_nocopy(pkgrd, "pkgver", &pkgver);
xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
if (xbps_find_pkg_in_array(pkgs, pkgver, NULL)) if (xbps_find_pkg_in_array(pkgs, pkgver, NULL))
return 0; return 0;
if ((pkgd = xbps_dictionary_copy_mutable(pkgrd)) == NULL)
return ENOMEM;
/* /*
* Add required objects into package dep's dictionary. * Add required objects into package dep's dictionary.
*/ */
if (autoinst && !xbps_dictionary_set_bool(pkgd, "automatic-install", true)) if (autoinst && !xbps_dictionary_set_bool(pkgd, "automatic-install", true))
return EINVAL; goto err;
/* /*
* Set a replaces to itself, so that virtual packages are always replaced. * Set a replaces to itself, so that virtual packages are always replaced.
@ -62,13 +66,15 @@ xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs,
free(self_replaced); free(self_replaced);
if (!xbps_dictionary_set(pkgd, "replaces", replaces)) if (!xbps_dictionary_set(pkgd, "replaces", replaces))
return EINVAL; goto err;
/* /*
* Add the dictionary into the unsorted queue. * Add the dictionary into the unsorted queue.
*/ */
if (!xbps_array_add(pkgs, pkgd)) if (!xbps_array_add(pkgs, pkgd))
return EINVAL; goto err;
xbps_dictionary_get_cstring_nocopy(pkgd, "repository", &repo);
xbps_set_cb_state(xhp, XBPS_STATE_TRANS_ADDPKG, 0, pkgver, xbps_set_cb_state(xhp, XBPS_STATE_TRANS_ADDPKG, 0, pkgver,
"Found %s (%s) in repository %s", pkgver, tract, repo); "Found %s (%s) in repository %s", pkgver, tract, repo);
@ -79,4 +85,7 @@ xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs,
xbps_object_release(pkgd); xbps_object_release(pkgd);
return 0; return 0;
err:
xbps_object_release(pkgd);
return EINVAL;
} }