From f9b1bb916c284bea00dd5549a43e0894b219d650 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Thu, 25 Nov 2021 00:01:12 +0100 Subject: daemon: Read substitute nar size as 'unsigned long long'. Fixes . Reported by Christopher Baines . Previously, the nar size returned by 'guix substitute' would be read as an 'int'; thus, values above 2^31 - 1 would be read and then stored as negative integers in the database. Regression introduced in 9dfa20a22ae0be3d3b01a7b3d422af97428c627e. * nix/libstore/build.cc (SubstitutionGoal::finished): Use templatized 'string2Int' instead of 'std::atoi' to get an 'unsigned long long', which is the type of 'hash.second'. * tests/store.scm ("substitute and large size"): New test. --- nix/libstore/build.cc | 3 ++- tests/store.scm | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 5697ae5a43..f6431bb726 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -3102,7 +3102,8 @@ void SubstitutionGoal::finished() throw Error(format("unknown hash algorithm in `%1%'") % hashStr); case htSHA256: hash.first = parseHash16or32(hashType, string(hashStr, n + 1)); - hash.second = std::atoi(statusList[2].c_str()); + if (!string2Int(statusList[2], hash.second)) + throw Error(format("invalid nar size for '%1%' substitute") % storePath); break; default: /* The database only stores SHA256 hashes, so compute it. */ diff --git a/tests/store.scm b/tests/store.scm index 11ca440aed..de12f6831e 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -976,6 +976,50 @@ (define failure (and (equal? (substitutable-path s) item) (substitutable-nar-size s))))))) +(test-equal "substitute and large size" + (+ 100 (expt 2 31)) ; + (with-store s + (let* ((size (+ 100 (expt 2 31))) ;does not fit in signed 'int' + (item (string-append (%store-prefix) + "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bad-size-" + (random-text))) + (nar (string-append (%substitute-directory) "/nar"))) + ;; Create a dummy nar to allow for substitution. + (call-with-output-file nar + (lambda (port) + (write-file-tree (store-path-package-name item) port + #:file-type+size (lambda _ + (values 'regular 12)) + #:file-port (lambda _ + (open-input-string "Hello world."))))) + + ;; Create fake substituter data, to be read by 'guix substitute'. + (call-with-output-file (string-append (%substitute-directory) + "/" (store-path-hash-part item) + ".narinfo") + (lambda (port) + (format port "StorePath: ~a +URL: file://~a +Compression: none +NarSize: ~a +NarHash: sha256:~a +References: +System: x86_64-linux~%" + item nar size + (bytevector->nix-base32-string (gcrypt:file-sha256 nar))))) + + ;; Remove entry from the local cache. + (false-if-exception + (delete-file-recursively (string-append (getenv "XDG_CACHE_HOME") + "/guix/substitute"))) + + ;; Make sure 'guix substitute' correctly communicates the above + ;; data. + (set-build-options s #:use-substitutes? #t + #:substitute-urls (%test-substitute-urls)) + (ensure-path s item) + (path-info-nar-size (query-path-info s item))))) + (test-assert "export/import several paths" (let* ((texts (unfold (cut >= <> 10) (lambda _ (random-text)) -- cgit v1.2.3