Memory fault error

Martin Simmons martin at lispworks.com
Fri Apr 27 10:42:23 UTC 2018


I think that answer is "you are not supposed to do that" because there is no
documentation for the slots of sensors_chip_name.  It could work by luck in
your C test case if the uninitialized name slot points to a null byte.

__Martin


>>>>> On Thu, 26 Apr 2018 20:16:43 -0700, Elliott Johnson said:
> 
> Hello,
> 
> If this is not the correct list to report a user error, I apologize and 
> will happily redirect my question where ever suitable.
> 
> I've been using cffi to make a trivial library to libsensors 
> https://github.com/groeck/lm-sensors and am getting an odd memory fault 
> error when referencing a string value from a groveled struct.  After 
> hitting my head against a wall for a day and a half, I thought I'd ask 
> in case it's a simple mistake.
> 
> Here's my information:
> 
> Running a 64 bit linux install.  My local version of the libsensors 
> library is as follows:
> 
> > elliott at desktop ~ $ file /usr/lib64/libsensors.so.4.4.0
> > /usr/lib64/libsensors.so.4.4.0: ELF 64-bit LSB shared object, x86-64, 
> > version 1 (SYSV), dynamically linked, stripped
> > elliott at desktop ~ $ sensors --version
> > sensors version 3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5 
> > with libsensors version 3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5
> 
> I'm using a fairly recent version of sbcl built from source that 
> (apparently) passed all of the tests after the build:
> 
> > CL-USER> (lisp-implementation-version)
> > "1.4.6.140-f8d5864d0"
> 
> My version of cffi appears to be the latest:
> 
> > CL-USER> (slot-value (asdf:find-system :cffi) 'asdf:version)
> > "0.19.0"
> 
> My system uses cffi-grovel and defines the following structs:
> 
> > (cstruct sensors-bus-id "sensors_bus_id"
> >          (type "type" :type :short)
> >          (nr "nr" :type :short))
> >
> > (cstruct sensors-chip-name "sensors_chip_name"
> >          (prefix "prefix" :type :string)
> >          (bus "bus" :type (:struct sensors-bus-id))
> >          (address "addr" :type :int)
> >          (path "path" :type :string))
> 
> These are based upon the definitions in sensors/sensors.h: 
> https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h
> 
> After asdf loading the system, the following groveler definitions are 
> created (had to dig these out of the cached build files):
> > (cffi:defcstruct (sensors-bus-id :size 4)
> >   (type :short :offset 0)
> >   (nr :short :offset 2))
> > (cl:defconstant size-of-sensors-bus-id (cffi:foreign-type-size 
> > '(:struct sensors-bus-id)))
> > (cffi:defcstruct (sensors-chip-name :size 24)
> >   (prefix :string :offset 0)
> >   (bus (:struct sensors-bus-id) :offset 8)
> >   (address :int :offset 12)
> >   (path :string :offset 16))
> > (cl:defconstant size-of-sensors-chip-name (cffi:foreign-type-size 
> > '(:struct sensors-chip-name)))
> All of the above appears to be correct, so I proceed to load the library:
> > (define-foreign-library libsensors
> >   (:unix (:or "libsensors.so.4" "libsensors.so"))
> >   (t (:default "libsensors.so")))
> > (use-foreign-library libsensors)
> No issues, so I define a c function from the c header file that parses a 
> sensor chip name-string into a struct:
> 
> > (defcfun ("sensors_parse_chip_name" cffi-sensors-parse-chip-name) :int
> >   "Parse a chip name to the internal representation.  Return 0 on 
> > success, <0 on error."
> >   (orig-name :string)
> >   (res (:pointer (:struct sensors-chip-name))))
> 
> Which is based upon the following header function declaration:
> 
> > int sensors_parse_chip_name(const char *orig_name, sensors_chip_name 
> > *res);
> 
> Then I implement a simple call to print out the parsed values (not 
> including the bus):
> 
> > (defun test-sensors-parse-chip-name (string)
> >   (with-foreign-object (name '(:struct sensors-chip-name))
> >     (unless (= 0 (cffi-sensors-parse-chip-name string name))
> >       (error "Failed to parse: ~A" string))
> >     (with-foreign-slots ((prefix address path)
> >                          name
> >                          (:struct sensors-chip-name))
> >       (format t "~%Prefix: '~A'" prefix)
> >       (format t "~%Address: '~A'" address)
> >       (format t "~%Path: '~A'" path))))
> 
> The above when executed gives the following output before the error:
> 
> > CL-LMSENSORS> (test-sensors-parse-chip-name "atk0110-acpi-0")
> >
> > Prefix: 'atk0110'
> > Address: '0'
> 
> And once it tries to access the path variable, it gives the following 
> error (sorry a lot rolls off the screen):
> 
> > Unhandled memory fault at #xE71B7.
> >    [Condition of type SB-SYS:MEMORY-FAULT-ERROR]
> >
> > Restarts:
> >  0: [RETRY] Retry SLIME REPL evaluation request.
> >  1: [*ABORT] Return to SLIME's top level.
> >  2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1002207F93}>)
> >
> > Backtrace:
> >   0: (CFFI::FOREIGN-STRING-LENGTH #.(SB-SYS:INT-SAP #X000E71B7) 
> > :ENCODING :UTF-8 :OFFSET 0)
> >       Locals:
> >         #:.DEFAULTING-TEMP. = :UTF-8
> >         #:.DEFAULTING-TEMP.#1 = 0
> >         #:N-SUPPLIED-0 = 1
> >         POINTER = #.(SB-SYS:INT-SAP #X000E71B7)
> >   1: (FOREIGN-STRING-TO-LISP #.(SB-SYS:INT-SAP #X000E71B7) :OFFSET 0 
> > :COUNT NIL :MAX-CHARS 4611686018427387900 :ENCODING :UTF-8$
> >       Locals:
> >         #:.DEFAULTING-TEMP. = 0
> >         #:.DEFAULTING-TEMP.#1 = NIL
> >         #:.DEFAULTING-TEMP.#2 = 4611686018427387900
> >         #:.DEFAULTING-TEMP.#3 = :UTF-8
> >         ENCODING = :UTF-8
> >         #:N-SUPPLIED-0 = 1
> >         POINTER = #.(SB-SYS:INT-SAP #X000E71B7)
> >   2: ((:METHOD TRANSLATE-FROM-FOREIGN (T CFFI::FOREIGN-STRING-TYPE)) 
> > #.(SB-SYS:INT-SAP #X000E71B7) #<CFFI::FOREIGN-STRING-TYPE $
> >   3: (TEST-SENSORS-PARSE-CHIP-NAME "atk0110-acpi-0") 
> My guess is I'm not defining the (:struct sensors-chip-name) correctly, 
> so that when sensors_parse_chip_name writes values into the struct, it 
> somehow overlaps into the path string.
> 
> When looking at the source for sensors_parse_chip_name I've noticed that 
> it does not set or access the path value at all.  So I decided to write 
> a small c program to test the native behavior:
> 
> > elliott at desktop ~ $ cat test-sensors.c
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include "sensors/sensors.h"
> >
> > int main( ) {
> >
> >   //sensors_init( NULL );
> >
> >   struct sensors_chip_name name;
> >
> >   int return_value = sensors_parse_chip_name( "atk0110-acpi-0", &name);
> >   if ( return_value != 0 ) {
> >     printf( "Failed to get a good return value." );
> >     exit( return_value );
> >   }
> >
> >   printf( "Printing the prefix: '%s'\n", name.prefix );
> >   printf( "Address: '%i'\n", name.addr );
> >   printf( "Printing path value: '%s'\n", name.path );
> >   printf ("\n exiting..." );
> >
> >   exit( 0 );
> > }
> > elliott at desktop ~ $ gcc test-sensors.c -l sensors -o test-sensors
> > elliott at desktop ~ $ ./test-sensors
> > Printing the prefix: 'atk0110'
> > Address: '0'
> > Printing path value: ''
> >
> >  exiting...
> No problems there, so I assume that the issue is all my lack of cffi-fu 
> training.  Any pointers (yes, pun intended) would be appreciated... 
> sorry for such a long read, but I hope it helps to have the background.  
> At the very least it helped me to frame the issue in my mind by writing 
> this.
> 
> Regards,
> Elliott
> 
> 



More information about the cffi-devel mailing list