database: Validate #:nar-size and #:time when registering store items.
* guix/store/database.scm (assert-integer): New procedure.
(update-or-insert): Use it to validate NAR-SIZE and TIME.
* tests/store-database.scm ("sqlite-register with incorrect size"): New
test.
			
			
This commit is contained in:
		
							parent
							
								
									9c4869fe9c
								
							
						
					
					
						commit
						13a7d2a538
					
				
					 2 changed files with 33 additions and 2 deletions
				
			
		| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
;;; GNU Guix --- Functional package management for GNU
 | 
					;;; GNU Guix --- Functional package management for GNU
 | 
				
			||||||
;;; Copyright © 2017, 2019 Caleb Ristvedt <caleb.ristvedt@cune.org>
 | 
					;;; Copyright © 2017, 2019 Caleb Ristvedt <caleb.ristvedt@cune.org>
 | 
				
			||||||
;;; Copyright © 2018, 2020 Ludovic Courtès <ludo@gnu.org>
 | 
					;;; Copyright © 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
 | 
				
			||||||
;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
 | 
					;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
 | 
				
			||||||
;;;
 | 
					;;;
 | 
				
			||||||
;;; This file is part of GNU Guix.
 | 
					;;; This file is part of GNU Guix.
 | 
				
			||||||
| 
						 | 
					@ -241,12 +241,26 @@ identifier.  Otherwise, return #f."
 | 
				
			||||||
  "INSERT INTO ValidPaths (path, hash, registrationTime, deriver, narSize)
 | 
					  "INSERT INTO ValidPaths (path, hash, registrationTime, deriver, narSize)
 | 
				
			||||||
VALUES (:path, :hash, :time, :deriver, :size)")
 | 
					VALUES (:path, :hash, :time, :deriver, :size)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define-inlinable (assert-integer proc in-range? key number)
 | 
				
			||||||
 | 
					  (unless (integer? number)
 | 
				
			||||||
 | 
					    (throw 'wrong-type-arg proc
 | 
				
			||||||
 | 
					           "Wrong type argument ~A: ~S" (list key number)
 | 
				
			||||||
 | 
					           (list number)))
 | 
				
			||||||
 | 
					  (unless (in-range? number)
 | 
				
			||||||
 | 
					    (throw 'out-of-range proc
 | 
				
			||||||
 | 
					           "Integer ~A out of range: ~S" (list key number)
 | 
				
			||||||
 | 
					           (list number))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define* (update-or-insert db #:key path deriver hash nar-size time)
 | 
					(define* (update-or-insert db #:key path deriver hash nar-size time)
 | 
				
			||||||
  "The classic update-if-exists and insert-if-doesn't feature that sqlite
 | 
					  "The classic update-if-exists and insert-if-doesn't feature that sqlite
 | 
				
			||||||
doesn't exactly have... they've got something close, but it involves deleting
 | 
					doesn't exactly have... they've got something close, but it involves deleting
 | 
				
			||||||
and re-inserting instead of updating, which causes problems with foreign keys,
 | 
					and re-inserting instead of updating, which causes problems with foreign keys,
 | 
				
			||||||
of course. Returns the row id of the row that was modified or inserted."
 | 
					of course. Returns the row id of the row that was modified or inserted."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ;; Make sure NAR-SIZE is valid.
 | 
				
			||||||
 | 
					  (assert-integer "update-or-insert" positive? #:nar-size nar-size)
 | 
				
			||||||
 | 
					  (assert-integer "update-or-insert" (cut >= <> 0) #:time time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ;; It's important that querying the path-id and the insert/update operation
 | 
					  ;; It's important that querying the path-id and the insert/update operation
 | 
				
			||||||
  ;; take place in the same transaction, as otherwise some other
 | 
					  ;; take place in the same transaction, as otherwise some other
 | 
				
			||||||
  ;; process/thread/fiber could register the same path between when we check
 | 
					  ;; process/thread/fiber could register the same path between when we check
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
;;; GNU Guix --- Functional package management for GNU
 | 
					;;; GNU Guix --- Functional package management for GNU
 | 
				
			||||||
;;; Copyright © 2017, 2018, 2020 Ludovic Courtès <ludo@gnu.org>
 | 
					;;; Copyright © 2017, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
 | 
				
			||||||
;;;
 | 
					;;;
 | 
				
			||||||
;;; This file is part of GNU Guix.
 | 
					;;; This file is part of GNU Guix.
 | 
				
			||||||
;;;
 | 
					;;;
 | 
				
			||||||
| 
						 | 
					@ -123,4 +123,21 @@
 | 
				
			||||||
         (pk 'welcome-exception! args)
 | 
					         (pk 'welcome-exception! args)
 | 
				
			||||||
         #t)))))
 | 
					         #t)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(test-equal "sqlite-register with incorrect size"
 | 
				
			||||||
 | 
					  'out-of-range
 | 
				
			||||||
 | 
					  (call-with-temporary-output-file
 | 
				
			||||||
 | 
					   (lambda (db-file port)
 | 
				
			||||||
 | 
					     (delete-file db-file)
 | 
				
			||||||
 | 
					     (catch #t
 | 
				
			||||||
 | 
					       (lambda ()
 | 
				
			||||||
 | 
					         (with-database db-file db
 | 
				
			||||||
 | 
					           (sqlite-register db #:path "/gnu/foo"
 | 
				
			||||||
 | 
					                            #:references '("/gnu/bar")
 | 
				
			||||||
 | 
					                            #:deriver "/gnu/foo.drv"
 | 
				
			||||||
 | 
					                            #:hash (string-append "sha256:" (make-string 64 #\e))
 | 
				
			||||||
 | 
					                            #:nar-size -1234))
 | 
				
			||||||
 | 
					         #f)
 | 
				
			||||||
 | 
					       (lambda (key . _)
 | 
				
			||||||
 | 
					         key)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(test-end "store-database")
 | 
					(test-end "store-database")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue