]> git.saurik.com Git - apt.git/commitdiff
invalid cache if architecture set doesn't match
authorDavid Kalnischkies <david@kalnischkies.de>
Sat, 10 May 2014 10:50:00 +0000 (12:50 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Sat, 10 May 2014 10:50:00 +0000 (12:50 +0200)
The cache heavily depends on the architecture(s) it is build for,
especially if you move from single- to multiarch. Adding a new
architecture to dpkg therefore has to be detected and must invalidate
the cache so that we don't operate on incorrect data.

The incorrect data will prevent us from doing otherwise sensible
actions (it doesn't allow bad things to happen) and the recovery is
simple and automatic in most cases, so this hides pretty well and is
also not as serious as it might sound at first.

Closes: 745036
apt-pkg/aptconfiguration.cc
apt-pkg/pkgcache.cc
apt-pkg/pkgcache.h
apt-pkg/pkgcachegen.cc
test/integration/test-bug-745036-new-foreign-invalidates-cache [new file with mode: 0755]

index 9982759c634d7cda87fc16df3d1e803925395114..94b6bc2468b8b5ef0e045dd4df7221afc58589fd 100644 (file)
@@ -540,7 +540,7 @@ std::string const Configuration::getBuildProfilesString() {
                return "";
        std::vector<std::string>::const_iterator p = profiles.begin();
        std::string list = *p;
-       for (; p != profiles.end(); ++p)
+       for (++p; p != profiles.end(); ++p)
           list.append(",").append(*p);
        return list;
 }
index c4ba9e24a67c7a98d7a20798546c4a8f3e493e4d..2b615363487ef34d6ebca301d9c75283f31769f1 100644 (file)
@@ -168,15 +168,23 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    if (Map.Size() < HeaderP->CacheFileSize)
       return _error->Error(_("The package cache file is corrupted, it is too small"));
 
+   if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->Architectures == 0)
+      return _error->Error(_("The package cache file is corrupted"));
+
    // Locate our VS..
-   if (HeaderP->VerSysName == 0 ||
-       (VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
+   if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
       return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
 
-   // Chcek the arhcitecture
-   if (HeaderP->Architecture == 0 ||
-       _config->Find("APT::Architecture") != StrP + HeaderP->Architecture)
-      return _error->Error(_("The package cache was built for a different architecture"));
+   // Check the architecture
+   std::vector<std::string> archs = APT::Configuration::getArchitectures();
+   std::vector<std::string>::const_iterator a = archs.begin();
+   std::string list = *a;
+   for (++a; a != archs.end(); ++a)
+      list.append(",").append(*a);
+   if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture ||
+        list != StrP + HeaderP->Architectures)
+      return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->Architectures, list.c_str());
+
    return true;
 }
                                                                        /*}}}*/
index 151de7d25e89dcdf3aba96b9a3615ccbbef07ba3..22dc6218cd85811f53a70e6e6e295e2ae4553156 100644 (file)
@@ -286,8 +286,10 @@ struct pkgCache::Header
    map_ptrloc StringList;
    /** \brief String representing the version system used */
    map_ptrloc VerSysName;
-   /** \brief Architecture(s) the cache was built against */
+   /** \brief native architecture the cache was built against */
    map_ptrloc Architecture;
+   /** \brief all architectures the cache was built against */
+   map_ptrloc Architectures;
    /** \brief The maximum size of a raw entry from the original Package file */
    unsigned long MaxVerFileSize;
    /** \brief The maximum size of a raw entry from the original Translation file */
index afc1c704c2abf986265c4aca76fcc5a10ed799ff..ac1cea0eb60f804d3d30235ed1f3d5a5f0246fab 100644 (file)
@@ -74,13 +74,31 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
       // Starting header
       *Cache.HeaderP = pkgCache::Header();
       map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
+      if (unlikely(idxVerSysName == 0))
+        return;
       Cache.HeaderP->VerSysName = idxVerSysName;
       // this pointer is set in ReMap, but we need it now for WriteUniqString
       Cache.StringItemP = (pkgCache::StringItem *)Map.Data();
       map_ptrloc const idxArchitecture = WriteUniqString(_config->Find("APT::Architecture"));
-      Cache.HeaderP->Architecture = idxArchitecture;
-      if (unlikely(idxVerSysName == 0 || idxArchitecture == 0))
+      if (unlikely(idxArchitecture == 0))
         return;
+      Cache.HeaderP->Architecture = idxArchitecture;
+
+      std::vector<std::string> archs = APT::Configuration::getArchitectures();
+      if (archs.size() > 1)
+      {
+        std::vector<std::string>::const_iterator a = archs.begin();
+        std::string list = *a;
+        for (++a; a != archs.end(); ++a)
+           list.append(",").append(*a);
+        map_ptrloc const idxArchitectures = WriteStringInMap(list);
+        if (unlikely(idxArchitectures == 0))
+           return;
+        Cache.HeaderP->Architectures = idxArchitectures;
+      }
+      else
+        Cache.HeaderP->Architectures = idxArchitecture;
+
       Cache.ReMap();
    }
    else
diff --git a/test/integration/test-bug-745036-new-foreign-invalidates-cache b/test/integration/test-bug-745036-new-foreign-invalidates-cache
new file mode 100755 (executable)
index 0000000..490cbec
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+insertpackage 'unstable' 'cool-foo' 'amd64' '1.0' 'Depends: foo'
+insertpackage 'unstable' 'foo' 'amd64' '1.0' 'Multi-Arch: foreign'
+insertinstalledpackage 'cool-foo' 'amd64' '1.0' 'Depends: foo'
+insertinstalledpackage 'foo' 'amd64' '1.0' 'Multi-Arch: foreign'
+
+setupaptarchive
+
+testsuccess aptget check -s
+
+configarchitecture 'amd64' 'i386'
+testequal 'E: The package cache was built for different architectures: amd64 vs amd64,i386' aptget check -s -o pkgCacheFile::Generate=false
+
+testsuccess aptget check -s
+
+insertinstalledpackage 'awesome-foo' 'i386' '1.0' 'Depends: foo'
+
+testsuccess aptget check -s
+
+testsuccess aptget update --no-download
+
+testsuccess aptget check -s