xbps-checkvers(8): fixed segfaults with missing vars on templates.

This commit is contained in:
Juan RP 2015-02-16 18:53:45 +01:00
parent 07d5e93bb0
commit 7cdba2ed14
3 changed files with 81 additions and 62 deletions

4
NEWS
View File

@ -1,5 +1,9 @@
xbps-0.44 (???): 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 * libxbps: globally check for unresolved reverse dependencies before accepting
the transaction. This catches more cases of broken packages due to incompatible the transaction. This catches more cases of broken packages due to incompatible
upgrades or unwanted removals. This also implements #46. upgrades or unwanted removals. This also implements #46.

View File

@ -43,6 +43,10 @@
#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
#endif #endif
#define GOT_PKGNAME_VAR 0x1
#define GOT_VERSION_VAR 0x2
#define GOT_REVISION_VAR 0x4
#ifdef _RCV_DEBUG #ifdef _RCV_DEBUG
# define _dprintf(...) \ # define _dprintf(...) \
do { \ do { \
@ -73,7 +77,8 @@ typedef struct _map_t {
typedef struct _rcv_t { typedef struct _rcv_t {
const char *prog, *fname; const char *prog, *fname;
char *input, *ptr, *xbps_conf, *rootdir, *distdir, *pkgdir; char *input, *ptr, *xbps_conf, *rootdir, *distdir, *pkgdir;
size_t len, have_vars; uint8_t have_vars;
size_t len;
map_t *env; map_t *env;
struct xbps_handle xhp; struct xbps_handle xhp;
xbps_dictionary_t pkgd; xbps_dictionary_t pkgd;
@ -369,13 +374,14 @@ error:
return buf; return buf;
} }
static int static void
rcv_get_pkgver(rcv_t *rcv) rcv_get_pkgver(rcv_t *rcv)
{ {
size_t klen, vlen; size_t klen, vlen;
map_item_t _item; map_item_t _item;
map_item_t *item = NULL; map_item_t *item = NULL;
char c, *ptr = rcv->ptr, *e, *p, *k, *v; char c, *ptr = rcv->ptr, *e, *p, *k, *v;
uint8_t vars = 0;
while ((c = *ptr) != '\0') { while ((c = *ptr) != '\0') {
if (c == '#') { if (c == '#') {
@ -389,46 +395,50 @@ rcv_get_pkgver(rcv_t *rcv)
if (c == 'u' && (strncmp("unset", ptr, 5)) == 0) { if (c == 'u' && (strncmp("unset", ptr, 5)) == 0) {
goto end; goto end;
} }
if (isalpha(c) || c == '_') { if ((e = strchr(ptr, '=')) == NULL)
e = strchr(ptr, '='); goto end;
p = strchr(ptr, '\n');
k = ptr; p = strchr(ptr, '\n');
v = e + 1; k = ptr;
klen = strlen(k) - strlen(e); v = e + 1;
vlen = strlen(v) - strlen(p); klen = strlen(k) - strlen(e);
if (v[0] == '"' && vlen == 1) { vlen = strlen(v) - strlen(p);
while (*ptr++ != '"'); if (v[0] == '"' && vlen == 1) {
goto end; 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;
} }
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; ptr = strchr(ptr, '\n') + 1;
} }
return (rcv->have_vars > 2) ? 0 : 1;
} }
static int static int
@ -441,8 +451,6 @@ rcv_process_file(rcv_t *rcv, const char *fname, rcv_check_func check)
rcv->env = NULL; rcv->env = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
rcv->have_vars = 0;
if (!rcv_load_file(rcv, fname)) { if (!rcv_load_file(rcv, fname)) {
map_destroy(rcv->env); map_destroy(rcv->env);
rcv->env = NULL; 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); map_add(rcv->env, "HOME", ehome);
rcv_get_pkgver(rcv); rcv_get_pkgver(rcv);
check(rcv); check(rcv);
map_destroy(rcv->env); map_destroy(rcv->env);
rcv->env = NULL; rcv->env = NULL;
return EXIT_SUCCESS; return 0;
} }
static void static void
@ -522,9 +528,18 @@ rcv_check_version(rcv_t *rcv)
char _srcver[BUFSIZ] = { '\0' }; char _srcver[BUFSIZ] = { '\0' };
char *srcver = _srcver; char *srcver = _srcver;
if (rcv->have_vars < 3) { assert(rcv);
printf("Error in '%s': missing '%s', '%s', or '%s' vars!\n",
rcv->fname, "pkgname", "version", "revision"); 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); exit(EXIT_FAILURE);
} }

View File

@ -75,9 +75,9 @@ EOF
xbps-rindex -d -a $PWD/*.xbps xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0 atf_check_equal $? 0
cd .. cd ..
out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out
atf_check_equal $? 0 atf_check_equal $? 1
atf_check_equal "$out" "" atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing pkgname variable!"
} }
atf_test_case srcpkg_missing_version atf_test_case srcpkg_missing_version
@ -101,9 +101,9 @@ EOF
xbps-rindex -d -a $PWD/*.xbps xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0 atf_check_equal $? 0
cd .. cd ..
out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out
atf_check_equal $? 0 atf_check_equal $? 1
atf_check_equal "$out" "" atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing version variable!"
} }
atf_test_case srcpkg_missing_revision atf_test_case srcpkg_missing_revision
@ -127,9 +127,9 @@ EOF
xbps-rindex -d -a $PWD/*.xbps xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0 atf_check_equal $? 0
cd .. cd ..
out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out
atf_check_equal $? 0 atf_check_equal $? 1
atf_check_equal "$out" "" atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing revision variable!"
} }
atf_test_case srcpkg_missing_pkgver atf_test_case srcpkg_missing_pkgver
@ -153,9 +153,9 @@ EOF
xbps-rindex -d -a $PWD/*.xbps xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0 atf_check_equal $? 0
cd .. cd ..
out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out
atf_check_equal $? 0 atf_check_equal $? 1
atf_check_equal "$out" "" atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing pkgname variable!"
} }
atf_test_case srcpkg_missing_pkgverrev atf_test_case srcpkg_missing_pkgverrev
@ -179,9 +179,9 @@ EOF
xbps-rindex -d -a $PWD/*.xbps xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0 atf_check_equal $? 0
cd .. cd ..
out=`xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages` xbps-checkvers -R $PWD/some_repo -D $PWD/void-packages 2>out
atf_check_equal $? 0 atf_check_equal $? 1
atf_check_equal "$out" "" atf_check_equal "$(cat out)" "ERROR: 'srcpkgs/A/template': missing pkgname variable!"
} }
atf_test_case reverts atf_test_case reverts