diff options
Diffstat (limited to 'libpkgconf/dependency.c')
| -rw-r--r-- | libpkgconf/dependency.c | 102 |
1 files changed, 59 insertions, 43 deletions
diff --git a/libpkgconf/dependency.c b/libpkgconf/dependency.c index 9b64809a4114..ce5237f2c154 100644 --- a/libpkgconf/dependency.c +++ b/libpkgconf/dependency.c @@ -2,6 +2,8 @@ * dependency.c * dependency parsing and management * + * SPDX-License-Identifier: pkgconf + * * Copyright (c) 2011, 2012, 2013 pkgconf authors (see AUTHORS). * * Permission to use, copy, modify, and/or distribute this software for any @@ -37,19 +39,16 @@ typedef enum { #define DEBUG_PARSE 0 -static const char * -dependency_to_str(const pkgconf_dependency_t *dep, char *buf, size_t buflen) +static inline const char * +dependency_to_buf(const pkgconf_dependency_t *dep, pkgconf_buffer_t *buf) { - pkgconf_strlcpy(buf, dep->package, buflen); + pkgconf_buffer_reset(buf); + pkgconf_buffer_append(buf, dep->package); + if (dep->version != NULL) - { - pkgconf_strlcat(buf, " ", buflen); - pkgconf_strlcat(buf, pkgconf_pkg_get_comparator(dep), buflen); - pkgconf_strlcat(buf, " ", buflen); - pkgconf_strlcat(buf, dep->version, buflen); - } + pkgconf_buffer_append_fmt(buf, " %s %s", pkgconf_pkg_get_comparator(dep), dep->version); - return buf; + return pkgconf_buffer_str(buf); } /* find a colliding dependency that is coloured differently */ @@ -75,29 +74,33 @@ find_colliding_dependency(const pkgconf_dependency_t *dep, const pkgconf_list_t static inline pkgconf_dependency_t * add_or_replace_dependency_node(pkgconf_client_t *client, pkgconf_dependency_t *dep, pkgconf_list_t *list) { - char depbuf[PKGCONF_ITEM_SIZE]; + pkgconf_buffer_t depbuf = PKGCONF_BUFFER_INITIALIZER; pkgconf_dependency_t *dep2 = find_colliding_dependency(dep, list); + const char *depstr = dependency_to_buf(dep, &depbuf); /* there is already a node in the graph which describes this dependency */ if (dep2 != NULL) { - char depbuf2[PKGCONF_ITEM_SIZE]; + pkgconf_buffer_t depbuf2 = PKGCONF_BUFFER_INITIALIZER; + const char *depstr2 = dependency_to_buf(dep2, &depbuf2); PKGCONF_TRACE(client, "dependency collision: [%s/%x] -- [%s/%x]", - dependency_to_str(dep, depbuf, sizeof depbuf), dep->flags, - dependency_to_str(dep2, depbuf2, sizeof depbuf2), dep2->flags); + depstr, dep->flags, depstr2, dep2->flags); /* prefer the uncoloured node, either dep or dep2 */ if (dep->flags && dep2->flags == 0) { - PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf, dep); + PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depstr, dep); + pkgconf_buffer_finalize(&depbuf); + pkgconf_buffer_finalize(&depbuf2); pkgconf_dependency_unref(dep->owner, dep); + return NULL; } else if (dep2->flags && dep->flags == 0) { - PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf2, dep2); + PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depstr2, dep2); pkgconf_node_delete(&dep2->iter, list); pkgconf_dependency_unref(dep2->owner, dep2); @@ -110,11 +113,15 @@ add_or_replace_dependency_node(pkgconf_client_t *client, pkgconf_dependency_t *d * fragment deduplication will handle the excessive fragments. */ PKGCONF_TRACE(client, "keeping both dependencies (harmless)"); + + pkgconf_buffer_finalize(&depbuf2); } - PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", dependency_to_str(dep, depbuf, sizeof depbuf), list, dep->flags); + PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", depstr, list, dep->flags); pkgconf_node_insert_tail(&dep->iter, pkgconf_dependency_ref(dep->owner, dep), list); + pkgconf_buffer_finalize(&depbuf); + /* This dependency is intentionally unowned. * * Internally we have no use for the returned type, and usually just @@ -135,6 +142,11 @@ pkgconf_dependency_addraw(pkgconf_client_t *client, pkgconf_list_t *list, const return NULL; dep->package = pkgconf_strndup(package, package_sz); + if (dep->package == NULL) + { + pkgconf_dependency_free_one(dep); + return NULL; + } if (version_sz != 0) dep->version = pkgconf_strndup(version, version_sz); @@ -169,6 +181,8 @@ pkgconf_dependency_add(pkgconf_client_t *client, pkgconf_list_t *list, const cha pkgconf_dependency_t *dep; dep = pkgconf_dependency_addraw(client, list, package, strlen(package), version, version != NULL ? strlen(version) : 0, compare, flags); + if (dep == NULL) + return NULL; return pkgconf_dependency_ref(dep->owner, dep); } @@ -211,6 +225,9 @@ pkgconf_dependency_free_one(pkgconf_dependency_t *dep) if (dep->version != NULL) free(dep->version); + if (dep->why != NULL) + free(dep->why); + free(dep); } @@ -306,30 +323,25 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h { parse_state_t state = OUTSIDE_MODULE; pkgconf_pkg_comparator_t compare = PKGCONF_CMP_ANY; - char cmpname[PKGCONF_ITEM_SIZE]; - size_t package_sz = 0, version_sz = 0, buf_sz = 0; - char *buf; + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + pkgconf_buffer_t cmpname = PKGCONF_BUFFER_INITIALIZER; + size_t package_sz = 0, version_sz = 0; char *start = NULL; char *ptr = NULL; char *vstart = NULL; char *package = NULL, *version = NULL; - char *cnameptr = cmpname; - char *cnameend = cmpname + PKGCONF_ITEM_SIZE - 1; + char *opstart = NULL; - if (!*depends) + if (depends == NULL || *depends == '\0') return; - memset(cmpname, '\0', sizeof cmpname); - - buf_sz = strlen(depends) * 2; - buf = calloc(1, buf_sz); - if (buf == NULL) - return; + if (!pkgconf_buffer_append(&buf, depends)) + goto out; - pkgconf_strlcpy(buf, depends, buf_sz); - pkgconf_strlcat(buf, " ", buf_sz); + if (!pkgconf_buffer_append(&buf, " ")) + goto out; - start = ptr = buf; + start = ptr = buf.base; while (*ptr) { @@ -391,23 +403,20 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h case BEFORE_OPERATOR: if (PKGCONF_IS_OPERATOR_CHAR(*ptr)) { + opstart = ptr; state = INSIDE_OPERATOR; - if (cnameptr < cnameend) - *cnameptr++ = *ptr; } break; case INSIDE_OPERATOR: if (PKGCONF_IS_OPERATOR_CHAR(*ptr)) - { - if (cnameptr < cnameend) - *cnameptr++ = *ptr; break; - } + pkgconf_buffer_reset(&cmpname); + pkgconf_buffer_append_slice(&cmpname, opstart, ptr - opstart); + compare = pkgconf_pkg_comparator_lookup_by_name(pkgconf_buffer_str(&cmpname)); state = AFTER_OPERATOR; - compare = pkgconf_pkg_comparator_lookup_by_name(cmpname); // fallthrough case AFTER_OPERATOR: @@ -428,9 +437,9 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h pkgconf_dependency_addraw(client, deplist_head, package, package_sz, version, version_sz, compare, flags); compare = PKGCONF_CMP_ANY; - cnameptr = cmpname; - memset(cmpname, 0, sizeof cmpname); package_sz = 0; + opstart = NULL; + pkgconf_buffer_reset(&cmpname); } if (state == OUTSIDE_MODULE) @@ -441,7 +450,9 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h ptr++; } - free(buf); +out: + pkgconf_buffer_finalize(&cmpname); + pkgconf_buffer_finalize(&buf); } /* @@ -463,7 +474,7 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h void pkgconf_dependency_parse(pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends, unsigned int flags) { - char *kvdepends = pkgconf_tuple_parse(client, &pkg->vars, depends, pkg->flags); + char *kvdepends = pkgconf_bytecode_eval_str(client, &pkg->vars, depends, NULL); pkgconf_dependency_parse_str(client, deplist, kvdepends, flags); free(kvdepends); @@ -490,6 +501,11 @@ pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *de return NULL; new_dep->package = strdup(dep->package); + if (new_dep->package == NULL) + { + pkgconf_dependency_free_one(new_dep); + return NULL; + } if (dep->version != NULL) new_dep->version = strdup(dep->version); |
