Remove the 'traverse_serial' fields which were added in 2.1.1.
Use the 'serial' field to track the current traversal.
Stop using 'identifier' to sort packages in the flattened solution.
Directly construct the flattened solution by a specific walk which
also preserves the relative order in Requires and Requires.private.
The topological sort is a single list, so don't fill requires_private.
Purely private dependencies are marked in dependency flags.
The ancestor flag is a pkg property, not a client property.
In our previous attempt to optimize this problem, we did not track the type of the
visit to the node, e.g. whether it came from evaluating Requires or Requires.private,
which resulted in some solutions being correctly incalculated due to greedy optimization
of the dependency graph.
We reintroduce this optimization by adding a second traversal serial as well as
re-introducing the PROPF_VISITED node property as well as a new PROPF_VISITED_PRIVATE
node property flag. This allows a node to be revisted at maximum two times per
traversal level.
Co-authored-by: Yi Chou <yich@google.com>
GCC 14 introduces a new -Walloc-size included in -Wextra which gives:
```
libpkgconf/personality.c:260:11: warning: allocation of insufficient size '1' for type 'pkgconf_cross_personality_t' {aka 'struct pkgconf_cross_personality_'} with size '48' [-Walloc-size]
libpkgconf/queue.c:46:33: warning: allocation of insufficient size '1' for type 'pkgconf_queue_t' {aka'struct pkgconf_queue_'} with size '16' [-Walloc-size]
libpkgconf/client.c:164:33: warning: allocation of insufficient size '1' for type 'pkgconf_client_t' {aka 'struct pkgconf_client_'} with size '120' [-Walloc-size]
libpkgconf/path.c:105:14: warning: allocation of insufficient size '1' for type 'pkgconf_path_t' {aka 'struct pkgconf_path_'} with size '24' [-Walloc-size]
libpkgconf/path.c:237:22: warning: allocation of insufficient size '1' for type 'pkgconf_path_t' {aka 'struct pkgconf_path_'} with size '24' [-Walloc-size]
libpkgconf/tuple.c:239:34: warning: allocation of insufficient size '1' for type 'pkgconf_tuple_t' {aka 'struct pkgconf_tuple_'} with size '24' [-Walloc-size]
libpkgconf/dependency.c:133:13: warning: allocation of insufficient size '1' for type 'pkgconf_dependency_t' {aka 'struct pkgconf_dependency_'} with size '44' [-Walloc-size]
libpkgconf/dependency.c:472:17: warning: allocation of insufficient size '1' for type 'pkgconf_dependency_t' {aka 'struct pkgconf_dependency_'} with size '44' [-Walloc-size]
libpkgconf/fragment.c:146:22: warning: allocation of insufficient size '1' for type 'pkgconf_fragment_t' {aka 'struct pkgconf_fragment_'} with size '24' [-Walloc-size]
libpkgconf/fragment.c:195:22: warning: allocation of insufficient size '1' for type 'pkgconf_fragment_t' {aka 'struct pkgconf_fragment_'} with size '24' [-Walloc-size]
libpkgconf/fragment.c:356:14: warning: allocation of insufficient size '1' for type 'pkgconf_fragment_t' {aka 'struct pkgconf_fragment_'} with size '24' [-Walloc-size]
libpkgconf/pkg.c:422:13: warning: allocation of insufficient size '1' for type 'pkgconf_pkg_t' {aka 'struct pkgconf_pkg_'} with size '188' [-Walloc-size]
libpkgconf/client.c:164:33: warning: allocation of insufficient size '1' for type 'pkgconf_client_t' {aka 'struct pkgconf_client_'} with size '224' [-Walloc-size]
libpkgconf/personality.c:260:11: warning: allocation of insufficient size '1' for type 'pkgconf_cross_personality_t' {aka 'struct pkgconf_cross_personality_'} with size '96' [-Walloc-size]
libpkgconf/dependency.c:133:13: warning: allocation of insufficient size '1' for type 'pkgconf_dependency_t' {aka 'struct pkgconf_dependency_'} with size '80' [-Walloc-size]
libpkgconf/dependency.c:472:17: warning: allocation of insufficient size '1' for type 'pkgconf_dependency_t' {aka 'struct pkgconf_dependency_'} with size '80' [-Walloc-size]
libpkgconf/path.c:105:14: warning: allocation of insufficient size '1' for type 'pkgconf_path_t' {aka 'struct pkgconf_path_'} with size '48' [-Walloc-size]
libpkgconf/path.c:237:22: warning: allocation of insufficient size '1' for type 'pkgconf_path_t' {aka 'struct pkgconf_path_'} with size '48' [-Walloc-size]
libpkgconf/queue.c:46:33: warning: allocation of insufficient size '1' for type 'pkgconf_queue_t' {aka 'struct pkgconf_queue_'} with size '32' [-Walloc-size]
libpkgconf/tuple.c:239:34: warning: allocation of insufficient size '1' for type 'pkgconf_tuple_t' {aka 'struct pkgconf_tuple_'} with size '48' [-Walloc-size]
libpkgconf/fragment.c:146:22: warning: allocation of insufficient size '1' for type 'pkgconf_fragment_t' {aka 'struct pkgconf_fragment_'} with size '48' [-Walloc-size]
libpkgconf/fragment.c:195:22: warning: allocation of insufficient size '1' for type 'pkgconf_fragment_t' {aka 'struct pkgconf_fragment_'} with size '48' [-Walloc-size]
libpkgconf/fragment.c:356:14: warning: allocation of insufficient size '1' for type 'pkgconf_fragment_t' {aka 'struct pkgconf_fragment_'} with size '48' [-Walloc-size]
libpkgconf/pkg.c:422:13: warning: allocation of insufficient size '1' for type 'pkgconf_pkg_t' {aka 'struct pkgconf_pkg_'} with size '360' [-Walloc-size]
```
The calloc prototype is:
```
void *calloc(size_t nmemb, size_t size);
```
So, just swap the number of members and size arguments to match the prototype, as
we're initialising 1 struct of size `sizeof(struct ...)`. GCC then sees we're not
doing anything wrong.
The only exception there is for argv which I fixed while at it.
Signed-off-by: Sam James <sam@gentoo.org>
ci/woodpecker/push/woodpecker Pipeline was successfulDetails
There are numerous edge cases where version is wrong or missing when
matching the dependency queue to resolved packages. This adds the
dependency name as it appears in the dependency queue to each package as
it is resolved, allowing for a simple and correct comparison when
printing.
Signed-off-by: Colin Gillespie <colin@cgillespie.xyz>
ci/woodpecker/push/woodpecker Pipeline was successfulDetails
fix https://github.com/pkgconf/pkgconf/issues/291
As defined in the C standard:
In all cases the argument is an int, the value of which shall
be representable as an unsigned char or shall equal the value
of the macro EOF. If the argument has any other value, the
behavior is undefined.
This is because they're designed to work with the int values returned
by getc or fgetc; they need extra work to handle a char value.
If EOF is -1 (as it almost always is), with 8-bit bytes, the allowed
inputs to the ctype(3) functions are:
{-1, 0, 1, 2, 3, ..., 255}.
However, on platforms where char is signed, such as x86 with the
usual ABI, code like
char *ptr = ...;
... isspace(*ptr) ...
may pass in values in the range:
{-128, -127, -126, ..., -2, -1, 0, 1, ..., 127}.
This has two problems:
1. Inputs in the set {-128, -127, -126, ..., -2} are forbidden.
2. The non-EOF byte 0xff is conflated with the value EOF = -1, so
even though the input is not forbidden, it may give the wrong
answer.
Casting char to unsigned int first before passing the result to
ctype(3) doesn't help: inputs like -128 are unchanged by this cast,
because (on a two's-complement machine with 32-bit int and unsigned
int), converting the signed char with integer value -128 to unsigned
int gives integer value 2^32 - 128 = 0xffffff80, which is out of
range, and which is converted in int back to -128, which is also out
of range.
It is necessary to cast char inputs to unsigned char first; you can
then cast to unsigned int if you like but there's no need because the
functions will always convert the argument to int by definition. So
the above fragment needs to be:
char *ptr = ...;
... isspace((unsigned char)*ptr) ...
This patch changes unsigned int casts to unsigned char casts, and
adds unsigned char casts where they are missing.
The code taken from rpmvercmp in pkg-config returns -1 if a is less than
b, 0 if a is equal to b, and 1 if a is greater than b. This matches the
expectations of the comparison operators that use this function.
However, the tilde handling, the NULL handling, and the docstring all do
the opposite.
This fixes the tilde handling, the NULL handling, and the docstring to
match the behavior of the rpmvercmp code and the expectations of the
comparison operators.
Otherwise in a case where A references B, and B references A, A and B
will have mutual ownership of each other and prevent each other from
being free'd.
We only want a reference to be added for the value inserted into the
list, not the one returned. The returned one is unowned until it reaches
the public dependency_add function, which returns an owned pointer
instead. This makes things semantically more correct.
Unfortunately, this means in a few cases we have to write some ugly
code like:
```c
pkgconf_dependency_t *dep = pkgcond_dependency_add("args");
pkgconf_dependency_unref(dep->owner, dep);
```
Prior to this commit, the code path responsible for prefix redefinition
(motivated by --define-prefix or otherwise) was visited more than
once, specifically since the check ignored pkg->owner->prefix_varname.
The current approach was to parse the .pc and, detect the prefix, throw
everything together and at the end replace all \ with / to not produce invalid
escape sequences.
This has the problem that escaping in .pc files is ignored and no longer
possible. Also in case the prefix path has a space in it the result would be
invalid because of missing escaping.
This changes the following things:
* We no longer normalize values at the end. Instead we assume .pc files use "/"
as a directory separator or "\\", same format as under Unix. "\" alone no
longer works. This shouldn't be a problem since most build tools produce .pc
files with "/" like meson, cmake, autotools.
* When injecting the prefix at runtime we convert the prefix to use "/" and
escape spaces so that in combination with the .pc content the result is a
valid escaped path value again.
This patch has been used in MSYS2 for some months now.
See #212
In case the version string has no whitespace then strcspn() returns
strlen() of the input, so whitespace is only found if len != strlen.
This fixes invalid warnings when parsing version fields.
If a file with a matching "uninstalled" name exists but cannot be
parsed, an invalid memory area is accessed.
How to reproduce:
$ touch poc-uninstalled.pc
$ PKG_CONFIG_PATH=. pkgconf poc
Windows allows both \ and / as valid path characters. A computed path
such as C:\development\libfoo\pkgconfig/foo.pc will result in a computed
pkgconf_pkg_t.id of "pkgconfig/foo".
Accordingly, correct the path normalization for checking for / after
the \ path has been dealt with in all cases.
Every version line has a newline at the end; the malformed whitespace checker
should just check for trailing spaces and tabs.
Resolves https://todo.sr.ht/~kaniini/pkgconf/15