[UFFI-Users] get-slot-value and nested structures

Hoehle, Joerg-Cyril Joerg-Cyril.Hoehle at t-systems.com
Mon Sep 13 06:27:57 MDT 2004


I'm a little more puzzled about get-slot-value. CLSQL has the following in db-mysql/mysql-api.lisp:
(uffi:def-struct mysql-bind
    (length (* :unsigned-long))
  (is-null (* mysql-bool))
  (buffer :pointer-void)
  (buffer-type :int)
  (buffer-length :unsigned-long)
  [more slots...]

and in db-mysql/mysql-sql.lisp:
(defmethod database-prepare [...]
	    (setf (uffi:get-slot-value binding 'mysql-bind 'buffer-length) 0)
	    (setf (uffi:get-slot-value binding 'mysql-bind 'is-null) 
		  (+ i (uffi:pointer-address is-null-ptr)))
	    (setf (uffi:get-slot-value binding 'mysql-bind 'length) 
		  (+ (* i 8) (uffi:pointer-address length-ptr)))

My naive understanding is that
[interpretation a] this should be a type error for both slots 'length and 'is-null because a call to uffi:make-pointer is missing to convert an int to a foreign pointer value for (* :unsigned-long) and (* mysql-bool).
IMHO, it's not acceptable to store an integer in a pointer object (although I believe this works in Allegro).

Alternatively [interpretation b], the existing pointer in the slot is used, not modified, and the given integer/bool value is dropped into the location that it points to.
This is what CLISP's FFI is doing, but that's not what I expected from UFFI after the previous discussion, because a recursive descent along pointers is not what I would expect from a sort of thin layer or least common denominator approach.

So what is the above code (more precisely, get-slot-value) doing and what is it supposed to do?
a1) yield a type error
a2) store a new pointer in the slots is-null and length
b) store an integer into the memory pointed to by the pointer slots?

>From looking at the surrounding code in mysql-sql.lisp, I suspect interpretation a2) is expected.
This IMHO means that the code is in fact missing (uffi:make-pointer around (+ ... uffi:pointer-address #) to be type-correct.
There are a few places in clsql where make-pointer is already used.

BTW, I fail to understand why the code setting the 'length slot uses (* i 8) instead of 4. It looks like a real buffer overflow bug. It's an array of num-fields :unsigned-long values which was allocated. The UFFI docs says it's implementation-dependent whether :unsigned-long is 32 or 64 bits. uffi:size-of-foreign-type may be required here?!?

I'm now wondering if this manual pointer arithmetic is necessary at all. In CLISP I could do something like the following and have the FFI correctly deal with pointer arithmetic and object sizes:
(dotimes (i num-fields)
  (with-c-place (binding ...)
    (setf (slot binding 'is-null)	; of some pointer type
          (c-var-address (element is-null-ptr i)))))
or        (foreign-address (ffi::%element is-null-ptr i)))))
It would require some uffi operation to take the address of an array element, which I haven't seen in the UFFI manual. (Additionaly, CLISP's ffi:element performs boundary checking).

Thanks for enlightening me,
	Jorg Hohle.

More information about the UFFI-Users mailing list