diff options
-rw-r--r-- | apt-pkg/acquire-method.cc | 2 | ||||
-rw-r--r-- | apt-pkg/acquire-method.h | 1 | ||||
-rw-r--r-- | apt-pkg/acquire-worker.cc | 4 | ||||
-rw-r--r-- | methods/http.cc | 12 | ||||
-rw-r--r-- | methods/http.h | 4 | ||||
-rw-r--r-- | methods/https.cc | 6 | ||||
-rw-r--r-- | methods/https.h | 5 | ||||
-rw-r--r-- | methods/server.cc | 8 | ||||
-rw-r--r-- | methods/server.h | 4 | ||||
-rwxr-xr-x | test/integration/test-apt-update-expected-size | 27 |
10 files changed, 68 insertions, 5 deletions
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index 82f2fb3ce..330854e75 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -372,6 +372,8 @@ int pkgAcqMethod::Run(bool Single) if (hash.empty() == false) Tmp->ExpectedHashes.push_back(HashString(*t, hash)); } + char *End; + Tmp->ExpectedSize = strtoll(LookupTag(Message, "Expected-Size", "0").c_str(), &End, 10); Tmp->Next = 0; // Append it to the list diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index cdeecc9a7..2e4e8281a 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -48,6 +48,7 @@ class pkgAcqMethod bool IndexFile; bool FailIgnore; HashStringList ExpectedHashes; + unsigned long long ExpectedSize; }; struct FetchResult diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 54be8e99f..8bd1618f4 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -526,6 +526,9 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) if (OutFd == -1) return false; + string ExpectedSize; + strprintf(ExpectedSize, "%llu", Item->Owner->FileSize); + string Message = "600 URI Acquire\n"; Message.reserve(300); Message += "URI: " + Item->URI; @@ -533,6 +536,7 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) HashStringList const hsl = Item->Owner->HashSums(); for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs) Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue(); + Message += "\nExpected-Size: " + ExpectedSize; Message += Item->Owner->Custom600Headers(); Message += "\n\n"; diff --git a/methods/http.cc b/methods/http.cc index f2a4a4db6..b076e59cc 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -64,7 +64,8 @@ const unsigned int CircleBuf::BW_HZ=10; // CircleBuf::CircleBuf - Circular input buffer /*{{{*/ // --------------------------------------------------------------------- /* */ -CircleBuf::CircleBuf(unsigned long long Size) : Size(Size), Hash(0) +CircleBuf::CircleBuf(unsigned long long Size) + : Size(Size), Hash(0), TotalWriten(0) { Buf = new unsigned char[Size]; Reset(); @@ -80,6 +81,7 @@ void CircleBuf::Reset() InP = 0; OutP = 0; StrPos = 0; + TotalWriten = 0; MaxGet = (unsigned long long)-1; OutQueue = string(); if (Hash != 0) @@ -217,6 +219,8 @@ bool CircleBuf::Write(int Fd) return false; } + + TotalWriten += Res; if (Hash != 0) Hash->Add(Buf + (OutP%Size),Res); @@ -651,6 +655,12 @@ bool HttpServerState::Go(bool ToFile, FileFd * const File) return _error->Errno("write",_("Error writing to output file")); } + if (ExpectedSize > 0 && File && File->Tell() > ExpectedSize) + { + return _error->Error("Writing more data than expected (%llu > %llu)", + File->Tell(), ExpectedSize); + } + // Handle commands from APT if (FD_ISSET(STDIN_FILENO,&rfds)) { diff --git a/methods/http.h b/methods/http.h index 1df9fa07d..40a88a7be 100644 --- a/methods/http.h +++ b/methods/http.h @@ -63,6 +63,8 @@ class CircleBuf public: Hashes *Hash; + // total amount of data that got written so far + unsigned long long TotalWriten; // Read data in bool Read(int Fd); @@ -81,8 +83,8 @@ class CircleBuf bool ReadSpace() const {return Size - (InP - OutP) > 0;}; bool WriteSpace() const {return InP - OutP > 0;}; - // Dump everything void Reset(); + // Dump everything void Stats(); CircleBuf(unsigned long long Size); diff --git a/methods/https.cc b/methods/https.cc index a74d2a38b..eec858417 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -82,6 +82,12 @@ HttpsMethod::write_data(void *buffer, size_t size, size_t nmemb, void *userp) if(me->File->Write(buffer, size*nmemb) != true) return false; + me->TotalWritten += size*nmemb; + if(me->TotalWritten > me->Queue->ExpectedSize) + return _error->Error("Writing more data than expected (%llu > %llu)", + me->TotalWritten, me->Queue->ExpectedSize); + + return size*nmemb; } diff --git a/methods/https.h b/methods/https.h index 45d1f7f63..0387cb9b5 100644 --- a/methods/https.h +++ b/methods/https.h @@ -66,11 +66,12 @@ class HttpsMethod : public pkgAcqMethod CURL *curl; FetchResult Res; HttpsServerState *Server; + unsigned long long TotalWritten; public: FileFd *File; - - HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), Server(NULL), File(NULL) + + HttpsMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), Server(NULL), TotalWritten(0), File(NULL) { curl = curl_easy_init(); }; diff --git a/methods/server.cc b/methods/server.cc index 4a961f454..223737901 100644 --- a/methods/server.cc +++ b/methods/server.cc @@ -532,6 +532,11 @@ int ServerMethod::Loop() // Run the data bool Result = true; + + // ensure we don't fetch too much + if (Queue->ExpectedSize > 0) + Server->ExpectedSize = Queue->ExpectedSize; + if (Server->HaveContent) Result = Server->RunData(File); @@ -605,7 +610,10 @@ int ServerMethod::Loop() QueueBack = Queue; } else + { + Server->Close(); Fail(true); + } } break; } diff --git a/methods/server.h b/methods/server.h index aa692ea93..0134a9538 100644 --- a/methods/server.h +++ b/methods/server.h @@ -49,6 +49,8 @@ struct ServerState URI Proxy; unsigned long TimeOut; + unsigned long long ExpectedSize; + protected: ServerMethod *Owner; @@ -73,7 +75,7 @@ struct ServerState bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;}; virtual void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0; StartPos = 0; Encoding = Closes; time(&Date); HaveContent = false; - State = Header; Persistent = false; Pipeline = true;}; + State = Header; Persistent = false; Pipeline = true; ExpectedSize = 0;}; virtual bool WriteResponse(std::string const &Data) = 0; /** \brief Transfer the data from the socket */ diff --git a/test/integration/test-apt-update-expected-size b/test/integration/test-apt-update-expected-size new file mode 100755 index 000000000..72812336d --- /dev/null +++ b/test/integration/test-apt-update-expected-size @@ -0,0 +1,27 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture "i386" + +insertpackage 'unstable' 'apt' 'all' '1.0' + +setupaptarchive --no-update +changetowebserver + +# normal update works fine +testsuccess aptget update + +# append junk at the end of the Packages.gz/Packages +SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)" +echo "1234567890" >> aptarchive/dists/unstable/main/binary-i386/Packages.gz +echo "1234567890" >> aptarchive/dists/unstable/main/binary-i386/Packages +NEW_SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)" +rm -f rootdir/var/lib/apt/lists/localhost* +testequal "W: Failed to fetch http://localhost:8080/dists/unstable/main/binary-i386/Packages Writing more data than expected ($NEW_SIZE > $SIZE) [IP: ::1 8080] + +E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq + |