Skip to content

Commit 5576e7f

Browse files
committed
Compare SHA256 to check if versions are really the same
If we know both SHA256, and they're different, the packages are. This approach stores the SHA256 only at runtime, avoiding the overhead of storing it on-disk, because when we update repositories we update all of them anyhow. Note that pkgCacheGenerator is hidden, so we can just modify its ABI, hooray. Closes: #931175 LP: #2029268
1 parent 2a88302 commit 5576e7f

File tree

5 files changed

+59
-5
lines changed

5 files changed

+59
-5
lines changed

apt-pkg/deb/deblistparser.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include <apt-pkg/pkgcache.h>
1515
#include <apt-pkg/pkgcachegen.h>
1616
#include <apt-pkg/tagfile.h>
17+
#ifdef APT_COMPILING_APT
18+
#include <apt-pkg/tagfile-keys.h>
19+
#endif
1720

1821
#include <string>
1922
#include <vector>
@@ -90,6 +93,13 @@ class APT_HIDDEN debListParser : public pkgCacheListParser
9093

9194
explicit debListParser(FileFd *File);
9295
virtual ~debListParser();
96+
97+
#ifdef APT_COMPILING_APT
98+
APT::StringView SHA256() const
99+
{
100+
return Section.Find(pkgTagSection::Key::SHA256);
101+
}
102+
#endif
93103
};
94104

95105
class APT_HIDDEN debDebFileParser : public debListParser

apt-pkg/pkgcachegen.cc

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <config.h>
1313

1414
#include <apt-pkg/configuration.h>
15+
#include <apt-pkg/deblistparser.h>
1516
#include <apt-pkg/error.h>
1617
#include <apt-pkg/fileutl.h>
1718
#include <apt-pkg/indexfile.h>
@@ -376,6 +377,12 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
376377
void const * oldMap = Map.Data();
377378

378379
auto Hash = List.VersionHash();
380+
APT::StringView ListSHA256;
381+
382+
bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
383+
auto DebList = dynamic_cast<debListParser *>(&List);
384+
if (DebList != nullptr)
385+
ListSHA256 = DebList->SHA256();
379386
if (Ver.end() == false)
380387
{
381388
/* We know the list is sorted so we use that fact in the search.
@@ -392,8 +399,18 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
392399
// Versionstrings are equal - is hash also equal?
393400
if (Res == 0)
394401
{
395-
if (List.SameVersion(Hash, Ver) == true)
396-
break;
402+
if (List.SameVersion(Hash, Ver))
403+
{
404+
// We do not have SHA256 for both, so we cannot compare them, trust the call from SameVersion()
405+
if (ListSHA256.empty() || VersionExtra[Ver->ID].SHA256[0] == 0)
406+
break;
407+
// We have SHA256 for both, so they must match.
408+
if (ListSHA256 == APT::StringView(VersionExtra[Ver->ID].SHA256, 64))
409+
break;
410+
if (Debug)
411+
std::cerr << "Found differing SHA256 for " << Pkg.Name() << "=" << Version.to_string() << std::endl;
412+
}
413+
397414
// sort (volatile) sources above not-sources like the status file
398415
if (CurrentFile == nullptr || (CurrentFile->Flags & pkgCache::Flag::NotSource) == 0)
399416
{
@@ -440,6 +457,8 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
440457
if (oldMap != Map.Data())
441458
LastVer = static_cast<map_pointer<pkgCache::Version> *>(Map.Data()) + (LastVer - static_cast<map_pointer<pkgCache::Version> const *>(oldMap));
442459
*LastVer = verindex;
460+
if (ListSHA256.size() == 64)
461+
memcpy(VersionExtra[Ver->ID].SHA256, ListSHA256.data(), 64);
443462

444463
if (unlikely(List.NewVersion(Ver) == false))
445464
return _error->Error(_("Error occurred while processing %s (%s%d)"),
@@ -869,6 +888,10 @@ map_pointer<pkgCache::Version> pkgCacheGenerator::NewVersion(pkgCache::VerIterat
869888
Ver->Hash = Hash;
870889
Ver->ID = Cache.HeaderP->VersionCount++;
871890

891+
// Allocate size for extra store
892+
if (VersionExtra.size() <= Ver->ID)
893+
VersionExtra.resize(Ver->ID + 1);
894+
872895
// try to find the version string in the group for reuse
873896
pkgCache::PkgIterator Pkg = Ver.ParentPkg();
874897
pkgCache::GrpIterator Grp = Pkg.Group();

apt-pkg/pkgcachegen.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/
7676
std::unordered_set<string_pointer, hash> strSections;
7777
#endif
7878

79+
struct VersionExtra
80+
{
81+
char SHA256[64];
82+
};
83+
std::vector<VersionExtra> VersionExtra{32 * 1024};
84+
7985
friend class pkgCacheListParser;
8086
typedef pkgCacheListParser ListParser;
8187

test/integration/framework

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,9 +1022,13 @@ insertpackage() {
10221022
Priority: $PRIORITY
10231023
Section: $SECTION
10241024
Installed-Size: 42
1025-
Size: 42
1026-
SHA256: 0000000000000000000000000000000000000000000000000000000000000000
1027-
Maintainer: Joe Sixpack <[email protected]>"
1025+
Size: 42"
1026+
if echo "$DEPENDENCIES" | grep -q SHA256:; then
1027+
:
1028+
else
1029+
echo "SHA256: 0000000000000000000000000000000000000000000000000000000000000000"
1030+
fi
1031+
echo "Maintainer: Joe Sixpack <[email protected]>"
10281032
test "$arch" = 'none' || echo "Architecture: $arch"
10291033
echo "Version: $VERSION
10301034
Filename: pool/${DISTSECTION}/${NAME}/${NAME}_${VERSION}_${arch}.deb"

test/integration/test-same-version-but-different

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ insertpackage 'testing' 'diff-size' 'all' '1' 'Size: 42'
3030
insertpackage 'unstable' 'diff-instsize' 'all' '1' 'Installed-Size: 21'
3131
insertpackage 'testing' 'diff-instsize' 'all' '1' 'Installed-Size: 42'
3232

33+
insertpackage 'unstable' 'diff-sha256' 'all' '1' 'SHA256: 0000000000000000000000000000000000000000000000000000000000000000'
34+
insertpackage 'testing' 'diff-sha256' 'all' '1' 'SHA256: 0000000000000000000000000000000000000000000000000000000000000001'
35+
3336
setupaptarchive
3437

3538
APTARCHIVE="$(readlink -f ./aptarchive)"
@@ -96,3 +99,11 @@ testsuccessequal "diff-instsize:
9699
500 file:${APTARCHIVE} testing/main all Packages
97100
1 500
98101
500 file:${APTARCHIVE} unstable/main all Packages" apt policy diff-instsize
102+
testsuccessequal "diff-sha256:
103+
Installed: (none)
104+
Candidate: 1
105+
Version table:
106+
1 500
107+
500 file:${APTARCHIVE} testing/main all Packages
108+
1 500
109+
500 file:${APTARCHIVE} unstable/main all Packages" apt policy diff-sha256

0 commit comments

Comments
 (0)