ironclad icon indicating copy to clipboard operation
ironclad copied to clipboard

Under ECL 24.5.10 byte-array-to-hex-string (v0.59) miscompiles due to (safety 0)

Open cdmojoli opened this issue 4 months ago • 1 comments

(In the exhibit below, scroll to the right to see the mismatch.)

CL-USER> (asdf:test-system :aws-sign4)
Expected presigned url:
"https://examplebucket.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20130524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=aeeed9bbccd4d02ee5c0109b86d86835f995330da4c265957d157751f604d404"

Got:
"https://examplebucket.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20130524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=3\0\0\0\0\0\0\0\0\0\001\0\0\0\0\0\0\0\03\0\0\0\02\03\0\0\0\0\01\0\0\01\003\02\0\0\03\0\0\02\03\0\03\0\0\0\0\0\00"

Simply changing safety to 1 solves this:


(defun byte-array-to-hex-string (vector &key (start 0) end (element-type 'base-char))
  "Return a string containing the hexadecimal representation of the
subsequence of VECTOR between START and END.  ELEMENT-TYPE controls
the element-type of the returned string."
  (declare (type (vector (unsigned-byte 8)) vector)
           (type fixnum start)
           (type (or null fixnum) end)
           (optimize (speed 3) (safety 1)))
  (let* ((end (or end (length vector)))
         (length (- end start))
         (hexdigits #.(coerce "0123456789abcdef" 'simple-base-string)))
    (loop with string = (ecase element-type
                          ;; so that the compiler optimization can jump in
                          (base-char (make-string (* length 2)
                                                  :element-type 'base-char))
                          (character (make-string (* length 2)
                                                  :element-type 'character)))
       for i from start below end
       for j from 0 below (* length 2) by 2
       do (let ((byte (aref vector i)))
#+ecl
            (declare (optimize (safety 1)))
#-ecl            
            (declare (optimize (safety 0)))
            (setf (aref string j)
                  (aref hexdigits (ldb (byte 4 4) byte))
                  (aref string (1+ j))
                  (aref hexdigits (ldb (byte 4 0) byte))))
       finally (return string))))

Notes:

  1. I am using Ubuntu 22.04 on x64.
  2. Ironclad tests pass.

cdmojoli avatar Oct 06 '24 06:10 cdmojoli