gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet-scheme] 02/02: dht/client: In 'datum->search-result', verify the


From: gnunet
Subject: [gnunet-scheme] 02/02: dht/client: In 'datum->search-result', verify the path lengths.
Date: Sun, 23 Jan 2022 17:59:18 +0100

This is an automated email from the git hooks/post-receive script.

maxime-devos pushed a commit to branch master
in repository gnunet-scheme.

commit b8e0342c9b116b3c648b60bbfb63d32959b95303
Author: Maxime Devos <maximedevos@telenet.be>
AuthorDate: Sun Jan 23 16:52:33 2022 +0000

    dht/client: In 'datum->search-result', verify the path lengths.
    
    * gnu/gnunet/dht/client.scm
      (&overly-large-paths,&malformed-path): New conditions.
      (datum->search-result): Verify the resulting /msgh:dht:client:result
      message would fit within a GNUnet message.  Verify the get path and
      put path are an integral number of path elements.
    * tests/distributed-hash-table.scm
      (path-length->size,test-malformed-path): New procedures.
      ("get-path size must be a multiple of the size of a path element")
      ("put-path size must be a multiple of the size of a path element"):
      New tests.
      ("copy-search-result: equal and independent")
      ("search-result-get-path, slice")
      ("search-result-get-path, empty")
      ("search-result-put-path, slice")
      ("search-result-put-path, empty")
      ("search-result get-path must be readable")
      ("search-result put-path must be readable"): Fix path sizes.
---
 gnu/gnunet/dht/client.scm        | 99 +++++++++++++++++++++++++++++++++++-----
 tests/distributed-hash-table.scm | 64 ++++++++++++++++++++------
 2 files changed, 138 insertions(+), 25 deletions(-)

diff --git a/gnu/gnunet/dht/client.scm b/gnu/gnunet/dht/client.scm
index 5925c86..1f922b2 100644
--- a/gnu/gnunet/dht/client.scm
+++ b/gnu/gnunet/dht/client.scm
@@ -32,6 +32,13 @@
          &overly-large-datum make-overly-large-datum overly-large-datum?
          overly-large-datum-type overly-large-datum-length
 
+         %overly-large-paths make-overly-large-paths overly-large-paths?
+         overly-large-paths-datum-length
+         overly-large-paths-get-path-length overly-large-paths-put-path-length
+
+         &malformed-path make-malformed-path malformed-path?
+         malformed-path-what malformed-path-size
+
          make-datum datum? datum-type datum-key datum-value datum-expiration
          datum->insertion insertion? insertion->datum
          insertion-desired-replication-level
@@ -85,11 +92,12 @@
          (only (gnu gnunet utils bv-slice)
                slice-length slice/read-only make-slice/read-write slice-copy!
                slice-slice verify-slice-readable)
+         (gnu gnunet utils hat-let)
          (only (rnrs base)
                and >= = quote * + - define begin ... let*
                quote case else values apply let cond if >
                <= expt assert exact? integer? lambda for-each
-               not expt min max)
+               not expt min max div-and-mod positive?)
          (only (rnrs control)
                unless when)
          (only (rnrs records syntactic)
@@ -157,6 +165,33 @@ appropriate exception."
       (type   overly-large-datum-type)
       ;; length of the (overly large) value
       (length overly-large-datum-length))
+
+    ;; A condition indicating that the combination of get path, put path
+    ;; and datum is too long -- it is the combination that is too long,
+    ;; not necessarily any part in particular.
+    ;;
+    ;; TODO: see &overly-large-datum
+    (define-condition-type &overly-large-paths &error
+      make-overly-large-paths
+      overly-large-paths?
+      ;; length of datum value (does not include the key or type)
+      (datum-length overly-large-paths-datum-length)
+      ;; The length (not the size!) of the get path, i.e. the number
+      ;; of path elements.  Zero if there is no get path.
+      (get-path-length overly-large-paths-get-path-length)
+      ;; Likewise, for the put path.
+      (put-path-length overly-large-paths-put-path-length))
+
+    ;; The would-be get-path or put-path does not have the correct size
+    ;; to be a path.
+    (define-condition-type &malformed-path &error
+      make-malformed-path
+      malformed-path?
+      ;; the symbol 'get-path' or 'put-path'
+      (what malformed-path-what)
+      ;; size of the would-be path (in octets)
+      (size malformed-path-size))
+
     ;; TODO: use the data structures below and test them
 
     ;; An key-value entry in the DHT.
@@ -255,16 +290,57 @@ be recovered with the accessor 
@code{search-result->datum}. It can be tested if
 an object is a search result with the predicate @code{search-result?}. The
 optional keyword arguments @code{get-path} and @code{put-path} are currently
 undocumented and untested."
-          ;; TODO: get-path and put-path
-          (%make (validate-datum datum)
-                 (and get-path
-                      (begin
-                        (verify-slice-readable 'get-path get-path)
-                        (slice/read-only get-path)))
-                 (and put-path
-                      (begin
-                        (verify-slice-readable 'put-path put-path)
-                        (slice/read-only put-path))))))))
+          ;; TODO: can a get-path exist without a put-path?
+          (let^ ((! (make-who)
+                    (make-who-condition 'datum->search-result))
+                 (! datum (validate-datum datum))
+                 (!^ (verify-path what path)
+                     "Test if @var{path} looks like a get path, put path or
+falsehood. If it is false, return @code{#false}, @code{0} and @code{0}.
+Otherwise, if it appears to be a valid path, return @var{path} as a readable
+bytevector slice, the size of the path and the length of the path.  If
+@var{path} is invalid, raise an appropriate exception."
+                    ((? (not path)
+                        (values #false 0 0))
+                     ;; Verify the slice is readable, and make sure the
+                     ;; 'what' field of the &missing-capabilities is
+                     ;; precise -- we can rely on slice/read-only to
+                     ;; perform capability checking, but then the 'what'
+                     ;; field wouldn't be correct.
+                     (_ (verify-slice-readable what path))
+                     ;; Verify the path actually consists of an integral number
+                     ;; of /dht:path-element structures.
+                     (! size (slice-length path))
+                     (<-- (length remainder)
+                          (div-and-mod size (sizeof /dht:path-element '())))
+                     (? (positive? remainder)
+                        (raise (condition
+                                (make-who)
+                                (make-malformed-path what size)))))
+                    ;; We could place an upper bound on the length of
+                    ;; @var{path} here, but that's a bit useless because
+                    ;; we will verify the total length (get-path + put-path)
+                    ;; later anyway.
+                    (values (slice/read-only path) size length))
+                 ;; Verify both the get-path and the put-path (if any),
+                 ;; remove writability and only keep readability.
+                 (<-- (get-path get-path-size get-path-length)
+                      (verify-path 'get-path get-path))
+                 (<-- (put-path put-path-size put-path-length)
+                      (verify-path 'put-path put-path))
+                 ;; Make sure the get-path, put-path, datum and
+                 ;; /:msg:dht:client:result header will fit in a GNUnet
+                 ;; message.  TODO: maybe also consider other messages?
+                 (! hypothetical-message-size
+                    (+ (sizeof /:msg:dht:client:result '())
+                       get-path-size put-path-size))
+                 (? (> hypothetical-message-size %max-message-size)
+                    (raise (condition
+                            (make-who)
+                            (make-overly-large-paths
+                             (slice-length (datum-value datum))
+                             get-path-length put-path-length)))))
+                (%make datum get-path put-path))))))
 
     (define (copy-search-result old)
       "Make a copy of the search result @var{old}, such that modifications to 
the
@@ -441,6 +517,7 @@ message header is assumed to be correct."
                  (extra-size (- (slice-length slice) (sizeof type '())))
                  (field (read% type '(field) header))
                  ...)
+            ;; TODO: C GNUnet uses /dht:path-element now ...
             (compare extra-size (* (+ field ...) (sizeof /peer-identity 
'()))))))
 
     ;; TODO reduce duplication with (gnu gnunet nse client) --- maybe introduce
diff --git a/tests/distributed-hash-table.scm b/tests/distributed-hash-table.scm
index c588c82..79e1831 100644
--- a/tests/distributed-hash-table.scm
+++ b/tests/distributed-hash-table.scm
@@ -16,7 +16,12 @@
 ;;
 ;; SPDX-License-Identifier: AGPL-3.0-or-later
 (define-module (test-distributed-hash-table))
-(import (gnu gnunet dht client)
+(import (quickcheck)
+       (quickcheck arbitrary)
+       (quickcheck generator)
+       (quickcheck property)
+       (gnu gnunet dht client)
+       (gnu gnunet dht struct)
        (gnu gnunet utils bv-slice)
        (gnu gnunet netstruct syntactic)
        (gnu gnunet hashcode struct)
@@ -249,12 +254,15 @@
       (and (datum=? old new)
           (datum-independent? old new)))))
 
+(define (path-length->size l)
+  (* l (sizeof /dht:path-element '())))
+
 ;; Detected a bug: the datum was not copied
 (test-assert "copy-search-result: equal and independent"
   (let* ((old-key (make-slice/read-write (sizeof /hashcode:512 '())))
         (old-value (make-slice/read-write 70))
-        (old-get-path (make-slice/read-write 9)) ; TODO: correct length
-        (old-put-path (make-slice/read-write 10)))
+        (old-get-path (make-slice/read-write (path-length->size 5)))
+        (old-put-path (make-slice/read-write (path-length->size 9))))
     (slice-u32-set! old-key 9 #xcabba9e (endianness big))
     (slice-u32-set! old-value 5 #xcabba9e (endianness big))
     (slice-u32-set! old-get-path 0 #xcabba9e (endianness big))
@@ -278,16 +286,15 @@
                       search-result-put-path))
 
 ;; These detected a bug: the capabilities were not restricted!
-;; TODO: length
 ;; TODO: can there be a get path without a put path?
-(search-result-get-path-slice-test "search-result-get-path, slice"
-                                  (make-slice/read-write 7))
-(search-result-get-path-slice-test "search-result-get-path, empty"
-                                  (make-slice/read-write 0))
-(search-result-put-path-slice-test "search-result-put-path, slice"
-                                  (make-slice/read-write 7))
-(search-result-put-path-slice-test "search-result-put-path, empty"
-                                  (make-slice/read-write 0))
+(search-result-get-path-slice-test
+ "search-result-get-path, slice" (make-slice/read-write (path-length->size 7)))
+(search-result-get-path-slice-test
+ "search-result-get-path, empty" (make-slice/read-write 0))
+(search-result-put-path-slice-test
+ "search-result-put-path, slice" (make-slice/read-write (path-length->size 7)))
+(search-result-put-path-slice-test
+ "search-result-put-path, empty" (make-slice/read-write 0))
 (test-equal "search-result-get-path, none"
   (list #false) ; TODO: drop 'list' when SRFI-64 bug is fixed
   (list (search-result-get-path (datum->search-result (make-a-datum)))))
@@ -301,7 +308,8 @@
  CAP_WRITE
  CAP_READ
  (datum->search-result
-  (make-a-datum) #:get-path (slice/write-only (make-slice/read-write 7))))
+  (make-a-datum) #:get-path
+  (slice/write-only (make-slice/read-write (path-length->size 7)))))
 
 (test-missing-caps
  "search-result get-path must be readable"
@@ -309,6 +317,34 @@
  CAP_WRITE
  CAP_READ
  (datum->search-result
-  (make-a-datum) #:put-path (slice/write-only (make-slice/read-write 7))))
+  (make-a-datum) #:put-path
+  (slice/write-only (make-slice/read-write (path-length->size 7)))))
+
+(define (test-malformed-path test-case what keyword)
+  (test-assert test-case
+    (quickcheck
+     (property
+      ((elements $natural)
+       (remainder
+       (arbitrary
+        (gen (choose-integer 1 (- (sizeof /dht:path-element '()) 1)))
+        (xform #false))))
+      (let ((size (+ remainder (* (sizeof /dht:path-element '())))))
+       (equal? (guard (c ((malformed-path? c)
+                          (list (condition-who c)
+                                (malformed-path-what c)
+                                (malformed-path-size c))))
+                 (datum->search-result
+                  (make-a-datum) keyword
+                  (make-slice/read-write size)))
+               (list 'datum->search-result what size)))))))
+
+(test-malformed-path
+ "get-path size must be a multiple of the size of a path element"
+ 'get-path #:get-path)
+
+(test-malformed-path
+ "put-path size must be a multiple of the size of a path element"
+ 'put-path #:put-path)
 
 (test-end)

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]