From ac81c0f9b79351258d3a29212f7fda312e5afeb5 Mon Sep 17 00:00:00 2001 From: josch Date: Tue, 19 Aug 2014 10:29:29 +0200 Subject: implement the updated build profile spec --- apt-pkg/deb/deblistparser.cc | 112 ++++++++++++--------- .../test-bug-661537-build-profiles-support | 86 ++++++++-------- test/libapt/parsedepends_test.cc | 29 ++++-- 3 files changed, 130 insertions(+), 97 deletions(-) diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 7d4fd52cf..8311b5d7d 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -635,72 +635,94 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, if (ParseRestrictionsList == true) { - // Parse a restrictions list - if (I != Stop && *I == '<') + // Parse a restrictions formula which is in disjunctive normal form: + // (foo AND bar) OR (blub AND bla) + + std::vector const profiles = APT::Configuration::getBuildProfiles(); + + // if the next character is a restriction list, then by default the + // dependency does not apply and the conditions have to be checked + // if the next character is not a restriction list, then by default the + // dependency applies + bool applies1 = (*I != '<'); + while (I != Stop) { + if (*I != '<') + break; + ++I; // malformed if (unlikely(I == Stop)) return 0; - std::vector const profiles = APT::Configuration::getBuildProfiles(); - const char *End = I; - bool Found = false; - bool NegRestriction = false; - while (I != Stop) - { - // look for whitespace or ending '>' - for (;End != Stop && !isspace(*End) && *End != '>'; ++End); - if (unlikely(End == Stop)) - return 0; - - if (*I == '!') + // if of the prior restriction list is already fulfilled, then + // we can just skip to the end of the current list + if (applies1) { + for (;End != Stop && *End != '>'; ++End); + I = ++End; + // skip whitespace + for (;I != Stop && isspace(*I) != 0; I++); + } else { + bool applies2 = true; + // all the conditions inside a restriction list have to be + // met so once we find one that is not met, we can skip to + // the end of this list + while (I != Stop) { - NegRestriction = true; - ++I; - } + // look for whitespace or ending '>' + // End now points to the character after the current term + for (;End != Stop && !isspace(*End) && *End != '>'; ++End); - std::string restriction(I, End); + if (unlikely(End == Stop)) + return 0; - std::string prefix = "profile."; - // only support for "profile" prefix, ignore others - if (restriction.size() > prefix.size() && - restriction.substr(0, prefix.size()) == prefix) - { - // get the name of the profile - restriction = restriction.substr(prefix.size()); + bool NegRestriction = false; + if (*I == '!') + { + NegRestriction = true; + ++I; + } + + std::string restriction(I, End); if (restriction.empty() == false && profiles.empty() == false && - std::find(profiles.begin(), profiles.end(), restriction) != profiles.end()) + std::find(profiles.begin(), profiles.end(), restriction) != profiles.end()) { - Found = true; - if (I[-1] != '!') - NegRestriction = false; - // we found a match, so fast-forward to the end of the wildcards - for (; End != Stop && *End != '>'; ++End); + if (NegRestriction) { + applies2 = false; + // since one of the terms does not apply we don't have to check the others + for (; End != Stop && *End != '>'; ++End); + } + } else { + if (!NegRestriction) { + applies2 = false; + // since one of the terms does not apply we don't have to check the others + for (; End != Stop && *End != '>'; ++End); + } + } + + if (*End++ == '>') { + I = End; + // skip whitespace + for (;I != Stop && isspace(*I) != 0; I++); + break; } - } - if (*End++ == '>') { I = End; - break; + // skip whitespace + for (;I != Stop && isspace(*I) != 0; I++); + } + if (applies2) { + applies1 = true; } - - I = End; - for (;I != Stop && isspace(*I) != 0; I++); } - - if (NegRestriction == true) - Found = !Found; - - if (Found == false) - Package = ""; /* not for this restriction */ } - // Skip whitespace - for (;I != Stop && isspace(*I) != 0; I++); + if (applies1 == false) { + Package = ""; //not for this restriction + } } if (I != Stop && *I == '|') diff --git a/test/integration/test-bug-661537-build-profiles-support b/test/integration/test-bug-661537-build-profiles-support index ae1403f71..6c850fdf9 100755 --- a/test/integration/test-bug-661537-build-profiles-support +++ b/test/integration/test-bug-661537-build-profiles-support @@ -11,18 +11,16 @@ insertinstalledpackage 'build-essential' 'all' '0' 'Multi-Arch: foreign' insertpackage 'unstable' 'foo' 'all' '1.0' insertpackage 'unstable' 'bar' 'all' '1.0' -insertsource 'unstable' 'buildprofiles' 'any' '1' 'Build-Depends: foo (>= 1.0) [i386 arm] , bar' +insertsource 'unstable' 'buildprofiles' 'any' '1' 'Build-Depends: foo (>= 1.0) [i386 arm] , bar' # table from https://wiki.debian.org/BuildProfileSpec -insertsource 'unstable' 'spec-1' 'any' '1' 'Build-Depends: foo ' -insertsource 'unstable' 'spec-2' 'any' '1' 'Build-Depends: foo ' -insertsource 'unstable' 'spec-3' 'any' '1' 'Build-Depends: foo ' -insertsource 'unstable' 'spec-4' 'any' '1' 'Build-Depends: foo ' -insertsource 'unstable' 'spec-5' 'any' '1' 'Build-Depends: foo ' -insertsource 'unstable' 'spec-6' 'any' '1' 'Build-Depends: foo ' -# multiple stanzas not supported: error out -insertsource 'unstable' 'spec-7' 'any' '1' 'Build-Depends: foo ' -insertsource 'unstable' 'spec-8' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-1' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-2' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-3' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-4' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-5' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-6' 'any' '1' 'Build-Depends: foo ' +insertsource 'unstable' 'spec-7' 'any' '1' 'Build-Depends: foo ' setupaptarchive @@ -72,7 +70,7 @@ Building dependency tree... 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' msgtest 'Check if version of installed dpkg is high enough for' 'build profiles support' -if dpkg --compare-versions "$(command dpkg-query --showformat='${Version}' --show dpkg)" 'ge' '1.17.2'; then +if dpkg --compare-versions "$(command dpkg-query --showformat='${Version}' --show dpkg)" 'ge' '1.17.14'; then msgpass testwithdpkg() { msgtest "Test with" "dpkg-checkbuilddeps -d '$1' -P '$2'" @@ -113,35 +111,37 @@ testprofile() { testwithdpkg "$2" "$3" "$4" } -testprofile 'spec-1' 'foo ' '' "$KEEP" -testprofile 'spec-1' 'foo ' 'stage1' "$DROP" -testprofile 'spec-1' 'foo ' 'notest' "$KEEP" -testprofile 'spec-1' 'foo ' 'stage1,notest' "$DROP" - -testprofile 'spec-2' 'foo ' '' "$DROP" -testprofile 'spec-2' 'foo ' 'stage1' "$KEEP" -testprofile 'spec-2' 'foo ' 'notest' "$DROP" -testprofile 'spec-2' 'foo ' 'stage1,notest' "$KEEP" - -testprofile 'spec-3' 'foo ' '' "$KEEP" -testprofile 'spec-3' 'foo ' 'stage1' "$DROP" -testprofile 'spec-3' 'foo ' 'notest' "$DROP" -testprofile 'spec-3' 'foo ' 'stage1,notest' "$DROP" - -testprofile 'spec-4' 'foo ' '' "$DROP" -testprofile 'spec-4' 'foo ' 'stage1' "$KEEP" -testprofile 'spec-4' 'foo ' 'notest' "$KEEP" -testprofile 'spec-4' 'foo ' 'stage1,notest' "$KEEP" - -testprofile 'spec-5' 'foo ' '' "$KEEP" -testprofile 'spec-5' 'foo ' 'stage1' "$DROP" -testprofile 'spec-5' 'foo ' 'notest' "$KEEP" -testprofile 'spec-5' 'foo ' 'stage1,notest' "$DROP" - -testprofile 'spec-6' 'foo ' '' "$KEEP" -testprofile 'spec-6' 'foo ' 'stage1' "$KEEP" -testprofile 'spec-6' 'foo ' 'notest' "$DROP" -testprofile 'spec-6' 'foo ' 'stage1,notest' "$KEEP" - -testfailure aptget build-dep spec-7 -s -testfailure aptget build-dep spec-8 -s +testprofile 'spec-1' 'foo ' '' "$KEEP" +testprofile 'spec-1' 'foo ' 'stage1' "$DROP" +testprofile 'spec-1' 'foo ' 'notest' "$KEEP" +testprofile 'spec-1' 'foo ' 'stage1,notest' "$DROP" + +testprofile 'spec-2' 'foo ' '' "$DROP" +testprofile 'spec-2' 'foo ' 'stage1' "$KEEP" +testprofile 'spec-2' 'foo ' 'notest' "$DROP" +testprofile 'spec-2' 'foo ' 'stage1,notest' "$KEEP" + +testprofile 'spec-3' 'foo ' '' "$KEEP" +testprofile 'spec-3' 'foo ' 'stage1' "$DROP" +testprofile 'spec-3' 'foo ' 'notest' "$DROP" +testprofile 'spec-3' 'foo ' 'stage1,notest' "$DROP" + +testprofile 'spec-4' 'foo ' '' "$DROP" +testprofile 'spec-4' 'foo ' 'stage1' "$DROP" +testprofile 'spec-4' 'foo ' 'notest' "$DROP" +testprofile 'spec-4' 'foo ' 'stage1,notest' "$KEEP" + +testprofile 'spec-5' 'foo ' '' "$DROP" +testprofile 'spec-5' 'foo ' 'stage1' "$DROP" +testprofile 'spec-5' 'foo ' 'notest' "$KEEP" +testprofile 'spec-5' 'foo ' 'stage1,notest' "$DROP" + +testprofile 'spec-6' 'foo ' '' "$DROP" +testprofile 'spec-6' 'foo ' 'stage1' "$KEEP" +testprofile 'spec-6' 'foo ' 'notest' "$DROP" +testprofile 'spec-6' 'foo ' 'stage1,notest' "$DROP" + +testprofile 'spec-7' 'foo ' '' "$KEEP" +testprofile 'spec-7' 'foo ' 'stage1' "$KEEP" +testprofile 'spec-7' 'foo ' 'notest' "$DROP" +testprofile 'spec-7' 'foo ' 'stage1,notest' "$KEEP" diff --git a/test/libapt/parsedepends_test.cc b/test/libapt/parsedepends_test.cc index 52eac8232..f644599bd 100644 --- a/test/libapt/parsedepends_test.cc +++ b/test/libapt/parsedepends_test.cc @@ -33,9 +33,10 @@ static void parseDependency(bool const StripMultiArch, bool const ParseArchFlag "os-for-me [ linux-any ], " "cpu-not-for-me [ any-armel ], " "os-not-for-me [ kfreebsd-any ], " - "not-in-stage1 , " - "not-in-stage1-or-nodoc , " - "only-in-stage1 , " + "not-in-stage1 , " + "not-stage1-and-not-nodoc , " + "not-stage1-or-not-nodoc , " + "unknown-profile , " "overlord-dev:any (= 7.15.3~) | overlord-dev:native (>> 7.15.5), " ; @@ -184,7 +185,7 @@ static void parseDependency(bool const StripMultiArch, bool const ParseArchFlag if (ParseRestrictionsList == true) { Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList); - EXPECT_EQ("", Package); // not-in-stage1-or-in-nodoc + EXPECT_EQ("", Package); // not-stage1-and-not-nodoc } else { EXPECT_EQ(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList)); Start = strstr(Start, ","); @@ -193,7 +194,16 @@ static void parseDependency(bool const StripMultiArch, bool const ParseArchFlag if (ParseRestrictionsList == true) { Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList); - EXPECT_EQ("only-in-stage1", Package); + EXPECT_EQ("not-stage1-or-not-nodoc", Package); + } else { + EXPECT_EQ(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList)); + Start = strstr(Start, ","); + Start++; + } + + if (ParseRestrictionsList == true) { + Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList); + EXPECT_EQ("", Package); // unknown-profile } else { EXPECT_EQ(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList)); Start = strstr(Start, ","); @@ -232,10 +242,11 @@ test: SCOPED_TRACE(std::string("ParseRestrictionsList: ") + (ParseRestrictionsList ? "true" : "false")); parseDependency(StripMultiArch, ParseArchFlags, ParseRestrictionsList); } - if (StripMultiArch == false) - if (ParseArchFlags == false) - ParseRestrictionsList = !ParseRestrictionsList; - ParseArchFlags = !ParseArchFlags; + if (StripMultiArch == false) { + if (ParseArchFlags == false) + ParseRestrictionsList = !ParseRestrictionsList; + ParseArchFlags = !ParseArchFlags; + } StripMultiArch = !StripMultiArch; runner++; -- cgit v1.2.3-70-g09d2 From 50e3155606fd9ab3940682267bbeb9b274170192 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 8 Oct 2014 11:12:45 +0200 Subject: add CVE-2014-7206 to 1.0.9.2 --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 6de853359..3896c0531 100644 --- a/debian/changelog +++ b/debian/changelog @@ -22,7 +22,7 @@ apt (1.0.9.2) unstable; urgency=medium [ Guillem Jover ] * apt-get: Create the temporary downloaded changelog inside tmpdir - (closes: #763780) + (closes: #763780) (CVE-2014-7206) -- Michael Vogt Thu, 02 Oct 2014 22:05:39 +0200 -- cgit v1.2.3-70-g09d2 From 180b693262d71381d650d10c3f95a5a70553f40f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 8 Oct 2014 11:35:48 +0200 Subject: methods/rsh.cc: replace strcat with std::string Instead of using strcat use a C++ std::string to avoid overflowing this buffer. Thanks to David Garfield Closes: #76442 --- methods/rsh.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/methods/rsh.cc b/methods/rsh.cc index bd46d2515..0e949160b 100644 --- a/methods/rsh.cc +++ b/methods/rsh.cc @@ -218,17 +218,20 @@ bool RSHConn::WriteMsg(std::string &Text,bool Sync,const char *Fmt,...) va_list args; va_start(args,Fmt); - // sprintf the description - char S[512]; - vsnprintf(S,sizeof(S) - 4,Fmt,args); + // sprintf into a buffer + char Tmp[1024]; + vsnprintf(Tmp,sizeof(Tmp),Fmt,args); va_end(args); + // concat to create the real msg + std::string Msg; if (Sync == true) - strcat(S," 2> /dev/null || echo\n"); + Msg = std::string(Tmp) + " 2> /dev/null || echo\n"; else - strcat(S," 2> /dev/null\n"); + Msg = std::string(Tmp) + " 2> /dev/null\n"; // Send it off + const char *S = Msg.c_str(); unsigned long Len = strlen(S); unsigned long Start = 0; while (Len != 0) -- cgit v1.2.3-70-g09d2 From 9227645d6d355f9f4332f400b8d58c8fa8f1e899 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 1 Sep 2014 16:09:48 +0200 Subject: Update Status field values handling Remove long obsolete (hold, hold-reinstreq, removal-failed) or just wrong (post-inst-failed vs postinst-failed) values, that have been autoconverted by dpkg at run-time to their new equivalents, so there should not be any such instance in any recent system (removal-failed since dpkg 1.1.4 in Apr 1996, hold and hold-reinstreq since dpkg 1.2.0 in May 1996). dpkg even stopped doing the mapping in 1.15.4 and 1.15.8 respectively. At the same time sort the list in the same order as they appear in the dpkg code. --- apt-pkg/deb/deblistparser.cc | 18 ++++++------------ doc/dpkg-tech.dbk | 28 +++++----------------------- 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 8311b5d7d..4eef66c2b 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -338,13 +338,9 @@ unsigned short debListParser::VersionHash() /* Status lines are of the form, Status: want flag status want = unknown, install, hold, deinstall, purge - flag = ok, reinstreq, hold, hold-reinstreq - status = not-installed, unpacked, half-configured, - half-installed, config-files, post-inst-failed, - removal-failed, installed - - Some of the above are obsolete (I think?) flag = hold-* and - status = post-inst-failed, removal-failed at least. + flag = ok, reinstreq + status = not-installed, config-files, half-installed, unpacked, + half-configured, triggers-awaited, triggers-pending, installed */ bool debListParser::ParseStatus(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) @@ -401,15 +397,13 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator &Pkg, // Process the flag field WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled}, + {"config-files",pkgCache::State::ConfigFiles}, + {"half-installed",pkgCache::State::HalfInstalled}, {"unpacked",pkgCache::State::UnPacked}, {"half-configured",pkgCache::State::HalfConfigured}, - {"installed",pkgCache::State::Installed}, - {"half-installed",pkgCache::State::HalfInstalled}, - {"config-files",pkgCache::State::ConfigFiles}, {"triggers-awaited",pkgCache::State::TriggersAwaited}, {"triggers-pending",pkgCache::State::TriggersPending}, - {"post-inst-failed",pkgCache::State::HalfConfigured}, - {"removal-failed",pkgCache::State::HalfInstalled}, + {"installed",pkgCache::State::Installed}, {NULL, 0}}; if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false) return _error->Error("Malformed 3rd word in the Status line"); diff --git a/doc/dpkg-tech.dbk b/doc/dpkg-tech.dbk index 660ccabc9..2584cf640 100644 --- a/doc/dpkg-tech.dbk +++ b/doc/dpkg-tech.dbk @@ -222,13 +222,11 @@ Where Want may be one of unknown, install, hold, deinstall, purge. Flag may -be one of ok, reinstreq, -hold, -hold-reinstreq. Status may -be one of not-installed, unpacked, -half-configured, installed, -half-installed config-files, -post-inst-failed, removal-failed. +be one of ok, reinstreq. +Status may +be one of not-installed, config-files, +half-installed, unpacked, +half-configured and installed. The states are as follows:- @@ -287,22 +285,6 @@ nothing else. - -post-inst-failed - - -Old name for half-configured. Do not use. - - - - -removal-failed - - -Old name for half-installed. Do not use. - - - The two last items are only left in dpkg for compatibility - they are -- cgit v1.2.3-70-g09d2