From 7cdba2ed14fdca58eb6bbdeb036f60d743e8b51d Mon Sep 17 00:00:00 2001 From: Juan RP Date: Mon, 16 Feb 2015 18:53:45 +0100 Subject: [PATCH] xbps-checkvers(8): fixed segfaults with missing vars on templates. --- NEWS | 4 + bin/xbps-checkvers/main.c | 109 ++++++++++++++----------- tests/xbps/xbps-checkvers/checkvers.sh | 30 +++---- 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/NEWS b/NEWS index d04e9ff9..07103d7e 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ xbps-0.44 (???): + * xbps-checkvers(8): this now does not segfault anymore when the source package + does not set required variables (pkgname/version/revision). Added new test + cases to verify its correctness. + * libxbps: globally check for unresolved reverse dependencies before accepting the transaction. This catches more cases of broken packages due to incompatible upgrades or unwanted removals. This also implements #46. diff --git a/bin/xbps-checkvers/main.c b/bin/xbps-checkvers/main.c index 138d58ca..fd8d08d7 100644 --- a/bin/xbps-checkvers/main.c +++ b/bin/xbps-checkvers/main.c @@ -43,6 +43,10 @@ #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) #endif +#define GOT_PKGNAME_VAR 0x1 +#define GOT_VERSION_VAR 0x2 +#define GOT_REVISION_VAR 0x4 + #ifdef _RCV_DEBUG # define _dprintf(...) \ do { \ @@ -73,7 +77,8 @@ typedef struct _map_t { typedef struct _rcv_t { const char *prog, *fname; char *input, *ptr, *xbps_conf, *rootdir, *distdir, *pkgdir; - size_t len, have_vars; + uint8_t have_vars; + size_t len; map_t *env; struct xbps_handle xhp; xbps_dictionary_t pkgd; @@ -369,13 +374,14 @@ error: return buf; } -static int +static void rcv_get_pkgver(rcv_t *rcv) { size_t klen, vlen; map_item_t _item; map_item_t *item = NULL; char c, *ptr = rcv->ptr, *e, *p, *k, *v; + uint8_t vars = 0; while ((c = *ptr) != '\0') { if (c == '#') { @@ -389,46 +395,50 @@ rcv_get_pkgver(rcv_t *rcv) if (c == 'u' && (strncmp("unset", ptr, 5)) == 0) { goto end; } - if (isalpha(c) || c == '_') { - e = strchr(ptr, '='); - p = strchr(ptr, '\n'); - k = ptr; - v = e + 1; - klen = strlen(k) - strlen(e); - vlen = strlen(v) - strlen(p); - if (v[0] == '"' && vlen == 1) { - while (*ptr++ != '"'); - goto end; - } - if (v[0] == '"') { v++; vlen--; } - if (v[vlen-1] == '"') { vlen--; } - if (vlen == 0) { goto end; } - _item = map_add_n(rcv->env, k, klen, v, vlen); - item = &rcv->env->items[_item.i]; - if (strchr(v, '$')) { - item->v.s = rcv_refs(rcv, item->v.s, item->v.len); - item->v.len = strlen(item->v.s); - item->v.vmalloc = 1; - } else { - item->v.vmalloc = 0; - } - if (strchr(item->v.s, '$') && item->v.vmalloc == 1) { - item->v.s = rcv_cmd(rcv, item->v.s, item->v.len); - item->v.len = strlen(item->v.s); - } - if ((strncmp("pkgname", k, klen) == 0) || - (strncmp("version", k, klen) == 0) || - (strncmp("revision", k, klen) == 0)) { - rcv->have_vars += 1; - } - /*printf("'%.*s':'%.*s'\n", item->k.len, item->k.s, item->v.len, item->v.s);*/ - if (rcv->have_vars > 2) break; + if ((e = strchr(ptr, '=')) == NULL) + goto end; + + p = strchr(ptr, '\n'); + k = ptr; + v = e + 1; + klen = strlen(k) - strlen(e); + vlen = strlen(v) - strlen(p); + if (v[0] == '"' && vlen == 1) { + while (*ptr++ != '"'); + goto end; } - end: + if (v[0] == '"') { v++; vlen--; } + if (v[vlen-1] == '"') { vlen--; } + if (vlen == 0) { goto end; } + _item = map_add_n(rcv->env, k, klen, v, vlen); + item = &rcv->env->items[_item.i]; + if (strchr(v, '$')) { + item->v.s = rcv_refs(rcv, item->v.s, item->v.len); + item->v.len = strlen(item->v.s); + item->v.vmalloc = 1; + } else { + item->v.vmalloc = 0; + } + if (strchr(item->v.s, '$') && item->v.vmalloc == 1) { + item->v.s = rcv_cmd(rcv, item->v.s, item->v.len); + item->v.len = strlen(item->v.s); + } + if (strncmp("pkgname", k, klen) == 0) { + rcv->have_vars |= GOT_PKGNAME_VAR; + vars++; + } else if (strncmp("version", k, klen) == 0) { + rcv->have_vars |= GOT_VERSION_VAR; + vars++; + } else if (strncmp("revision", k, klen) == 0) { + rcv->have_vars |= GOT_REVISION_VAR; + vars++; + } + /*printf("'%.*s':'%.*s'\n", item->k.len, item->k.s, item->v.len, item->v.s);*/ + if (vars > 2) + return; +end: ptr = strchr(ptr, '\n') + 1; } - - return (rcv->have_vars > 2) ? 0 : 1; } static int @@ -441,8 +451,6 @@ rcv_process_file(rcv_t *rcv, const char *fname, rcv_check_func check) rcv->env = NULL; return EXIT_FAILURE; } - rcv->have_vars = 0; - if (!rcv_load_file(rcv, fname)) { map_destroy(rcv->env); rcv->env = NULL; @@ -457,13 +465,11 @@ rcv_process_file(rcv_t *rcv, const char *fname, rcv_check_func check) map_add(rcv->env, "HOME", ehome); rcv_get_pkgver(rcv); - check(rcv); - map_destroy(rcv->env); rcv->env = NULL; - return EXIT_SUCCESS; + return 0; } static void @@ -522,9 +528,18 @@ rcv_check_version(rcv_t *rcv) char _srcver[BUFSIZ] = { '\0' }; char *srcver = _srcver; - if (rcv->have_vars < 3) { - printf("Error in '%s': missing '%s', '%s', or '%s' vars!\n", - rcv->fname, "pkgname", "version", "revision"); + assert(rcv); + + if ((rcv->have_vars & GOT_PKGNAME_VAR) == 0) { + fprintf(stderr, "ERROR: '%s': missing pkgname variable!\n", rcv->fname); + exit(EXIT_FAILURE); + } + if ((rcv->have_vars & GOT_VERSION_VAR) == 0) { + fprintf(stderr, "ERROR: '%s': missing version variable!\n", rcv->fname); + exit(EXIT_FAILURE); + } + if ((rcv->have_vars & GOT_REVISION_VAR) == 0) { + fprintf(stderr, "ERROR: '%s': missing revision variable!\n", rcv->fname); exit(EXIT_FAILURE); } diff --git a/tests/xbps/xbps-checkvers/checkvers.sh b/tests/xbps/xbps-checkvers/checkvers.sh index 16565874..2a2afa05 100755 --- a/tests/xbps/xbps-checkvers/checkvers.sh +++ b/tests/xbps/xbps-checkvers/checkvers.sh @@ -75,9 +75,9 @@ EOF xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` - atf_check_equal $? 0 - atf_check_equal "$out" "" + xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out + atf_check_equal $? 1 + atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing pkgname variable!" } atf_test_case srcpkg_missing_version @@ -101,9 +101,9 @@ EOF xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` - atf_check_equal $? 0 - atf_check_equal "$out" "" + xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out + atf_check_equal $? 1 + atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing version variable!" } atf_test_case srcpkg_missing_revision @@ -127,9 +127,9 @@ EOF xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` - atf_check_equal $? 0 - atf_check_equal "$out" "" + xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out + atf_check_equal $? 1 + atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing revision variable!" } atf_test_case srcpkg_missing_pkgver @@ -153,9 +153,9 @@ EOF xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` - atf_check_equal $? 0 - atf_check_equal "$out" "" + xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out + atf_check_equal $? 1 + atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing pkgname variable!" } atf_test_case srcpkg_missing_pkgverrev @@ -179,9 +179,9 @@ EOF xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` - atf_check_equal $? 0 - atf_check_equal "$out" "" + xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out + atf_check_equal $? 1 + atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing pkgname variable!" } atf_test_case reverts