From 61843f539513b3e661dac55717e6d7cc0b8f9b0c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 18 Jul 2013 16:52:31 +0200 Subject: skip all Description fields in apt-cache, not just first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given a Packages file like: […] Description: foo bar baz moo moo moo Multi-Arch: foreign Description-md5: 97e204a9f4ad8c681dbd54ec7c505251 […] We have to display the Multi-Arch flag field as well as the fields after the Description-md5, but not this field itself, as we already have one printed alongside the Description we display. Closes: 717254 --- cmdline/apt-cache.cc | 52 +++++++++++++++------- .../test-bug-712435-missing-descriptions | 52 +++++++++++++++++++++- 2 files changed, 86 insertions(+), 18 deletions(-) diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index fb4467c2c..336ac544b 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1127,6 +1127,22 @@ bool Dotty(CommandLine &CmdL) // --------------------------------------------------------------------- /* This displays the package record from the proper package index file. It is not used by DumpAvail for performance reasons. */ + +static unsigned char const* skipDescriptionFields(unsigned char const * DescP) +{ + while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL) + { + if (DescP[1] == ' ') + DescP += 2; + else if (strncmp((char*)DescP, "\nDescription", strlen("\nDescription")) == 0) + DescP += strlen("\nDescription"); + else + break; + } + if (DescP != NULL) + ++DescP; + return DescP; +} bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V) { pkgCache *Cache = CacheFile.GetPkgCache(); @@ -1184,32 +1200,34 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V) cout << std::endl << "Description-md5: " << Desc.md5() << std::endl; // Find the first field after the description (if there is any) - while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL) - { - if (DescP[1] == ' ') - DescP += 2; - else if (strncmp((char*)DescP, "\nDescription", strlen("\nDescription")) == 0) - DescP += strlen("\nDescription"); - else - break; - } - if (DescP != NULL) - ++DescP; + DescP = skipDescriptionFields(DescP); } - // if we have no translation, we found a lonely Description-md5, so don't skip it + // else we have no translation, so we found a lonely Description-md5 -> don't skip it - if (DescP != NULL) + // write the rest of the buffer, but skip mixed in Descriptions* fields + while (DescP != NULL) { - // write the rest of the buffer - const unsigned char *end=&Buffer[V.FileList()->Size]; - if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP)) + const unsigned char * const Start = DescP; + const unsigned char *End = (unsigned char*)strstr((char*)DescP, "\nDescription"); + if (End == NULL) + { + End = &Buffer[V.FileList()->Size]; + DescP = NULL; + } + else + { + ++End; // get the newline into the output + DescP = skipDescriptionFields(End + strlen("Description")); + } + size_t const length = End - Start; + if (fwrite(Start, 1, length, stdout) < length) { delete [] Buffer; return false; } } - // write a final newline (after the description) + // write a final newline after the last field cout< aptarchive/Packages +$PACKAGESTANZA + +Package: apt-intermixed +$PACKAGESTANZA +$DESCRIPTION +X-Some-Flag: yes +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +Package: apt-intermixed2 +$PACKAGESTANZA +$DESCRIPTION +X-Some-Flag: yes +$TRANSDESCRIPTION +X-Foo-Flag: Something with a Description +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +X-Bar-Flag: no + +Package: apt-intermixed3 +$PACKAGESTANZA +$DESCRIPTION +X-Some-Flag: yes +$TRANSDESCRIPTION +X-Foo-Flag: Something with a Description +X-Bar-Flag: no +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" > aptarchive/Packages + setupaptarchive @@ -87,3 +112,28 @@ Description-md5: dddddddddddddddddddddddddddddddd testequal "Package: apt-none $PACKAGESTANZA " aptcache show apt-none + +testequal "Package: apt-intermixed +$PACKAGESTANZA +$DESCRIPTION +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +X-Some-Flag: yes +" aptcache show apt-intermixed + +testequal "Package: apt-intermixed2 +$PACKAGESTANZA +$DESCRIPTION +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +X-Some-Flag: yes +X-Foo-Flag: Something with a Description +X-Bar-Flag: no +" aptcache show apt-intermixed2 + +testequal "Package: apt-intermixed3 +$PACKAGESTANZA +$DESCRIPTION +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +X-Some-Flag: yes +X-Foo-Flag: Something with a Description +X-Bar-Flag: no +" aptcache show apt-intermixed3 -- cgit v1.2.3 From 922f07986b93ce7866f89917e3a475e6a4b3941c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 18 Jul 2013 19:22:29 +0200 Subject: fix 'apt-cache search' crash with missing description Beside the earlier fixed 'apt-cache show', 'showpkg' and 'search' deal with descriptions. 'showpkg' was fixed by fixing the cache generation for 'show', but 'search' still segfaulted. On the upside, it doesn't segfault any longer, on the downside, if a package has no description at all (aka: not in the Packages file and not in a Translation-* file) the package can't be found with 'search', even if we search only by name. That is a shortcoming in the code, but fixing it means rewriting it completely for dubious gain at best. So this commit just skips packages without a description and is done. Closes: 647590 --- cmdline/apt-cache.cc | 33 ++++++++++++++-------- .../test-bug-712435-missing-descriptions | 26 +++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 336ac544b..5d1ee5615 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1130,12 +1130,14 @@ bool Dotty(CommandLine &CmdL) static unsigned char const* skipDescriptionFields(unsigned char const * DescP) { + char const * const TagName = "\nDescription"; + size_t const TagLen = strlen(TagName); while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL) { if (DescP[1] == ' ') DescP += 2; - else if (strncmp((char*)DescP, "\nDescription", strlen("\nDescription")) == 0) - DescP += strlen("\nDescription"); + else if (strncmp((char*)DescP, TagName, TagLen) == 0) + DescP += TagLen; else break; } @@ -1166,11 +1168,12 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V) if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false) return false; - // Read the record - unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+1]; - Buffer[V.FileList()->Size] = '\n'; - if (PkgF.Seek(V.FileList()->Offset) == false || - PkgF.Read(Buffer,V.FileList()->Size) == false) + // Read the record (and ensure that it ends with a newline and NUL) + unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+2]; + Buffer[Vf->Size] = '\n'; + Buffer[Vf->Size+1] = '\0'; + if (PkgF.Seek(Vf->Offset) == false || + PkgF.Read(Buffer,Vf->Size) == false) { delete [] Buffer; return false; @@ -1181,7 +1184,7 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V) if (DescP != NULL) ++DescP; else - DescP = Buffer + V.FileList()->Size; + DescP = Buffer + Vf->Size; // Write all but Description if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer)) @@ -1211,7 +1214,7 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V) const unsigned char *End = (unsigned char*)strstr((char*)DescP, "\nDescription"); if (End == NULL) { - End = &Buffer[V.FileList()->Size]; + End = &Buffer[Vf->Size]; DescP = NULL; } else @@ -1318,7 +1321,11 @@ bool Search(CommandLine &CmdL) pkgCache::VerIterator V = Plcy->GetCandidateVer(P); if (V.end() == false) { - DFList[G->ID].Df = V.TranslatedDescription().FileList(); + pkgCache::DescIterator const D = V.TranslatedDescription(); + //FIXME: packages without a description can't be found + if (D.end() == true) + continue; + DFList[G->ID].Df = D.FileList(); DFList[G->ID].ID = G->ID; } @@ -1333,7 +1340,11 @@ bool Search(CommandLine &CmdL) continue; unsigned long id = Prv.OwnerPkg().Group()->ID; - DFList[id].Df = V.TranslatedDescription().FileList(); + pkgCache::DescIterator const D = V.TranslatedDescription(); + //FIXME: packages without a description can't be found + if (D.end() == true) + continue; + DFList[id].Df = D.FileList(); DFList[id].ID = id; size_t const PrvPatternOffset = id * NumPatterns; diff --git a/test/integration/test-bug-712435-missing-descriptions b/test/integration/test-bug-712435-missing-descriptions index c61bea452..53ecbbeb3 100755 --- a/test/integration/test-bug-712435-missing-descriptions +++ b/test/integration/test-bug-712435-missing-descriptions @@ -137,3 +137,29 @@ X-Some-Flag: yes X-Foo-Flag: Something with a Description X-Bar-Flag: no " aptcache show apt-intermixed3 + +msgtest 'Test that no description does not destroy' 'showpkg' +aptcache showpkg apt-none | sed 's#/tmp/.*_aptarchive_#/tmp/aptarchive_#' >showpkg.explosion && msgpass || msgfail +testfileequal showpkg.explosion 'Package: apt-none +Versions: +0.9.7.8 (/tmp/aptarchive_Packages) + + +Reverse Depends: +Dependencies: +0.9.7.8 - +Provides: +0.9.7.8 - +Reverse Provides: ' + +testempty aptcache search nonexistentstring + +# packages without a description can't be found +testequal 'apt-normal - commandline package manager +apt-both-below - commandline package manager +apt-both-middle - commandline package manager +apt-both-top - commandline package manager +apt-trans - commandline package manager +apt-intermixed - commandline package manager +apt-intermixed2 - commandline package manager +apt-intermixed3 - commandline package manager' aptcache search apt -- cgit v1.2.3