Same Problem found with Showwell-11.5 on openSUSE 12.1 (x86_64).
Problem analysis (gdb trace/comments):
$ gdb ./shotwell
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff02b5540 in __memcpy_ssse3 () from /lib64/libc.so.6
(gdb) where
#0 0x00007ffff02b5540 in __memcpy_ssse3 () from /lib64/libc.so.6
#1 0x0000000000604c9a in gp_load_file_into_buffer (context=0x1911740, camera=0x194c950, folder=0x1873270 "/DCIM/100CANON", filename=0xe33a50 "IMG_0001.JPG",
filetype=GP_FILE_TYPE_EXIF, result_length1=0x7fffffffb1c0, error=0x7fffffffb1b8) at /home/seiderer/Work/shotwell/shotwell/src/camera/GPhoto.vala:248
#2 0x0000000000603c87 in gp_load_metadata (context=0x1911740, camera=0x194c950, folder=0x1873270 "/DCIM/100CANON", filename=0xe33a50 "IMG_0001.JPG", error=
0x7fffffffb2a8) at /home/seiderer/Work/shotwell/shotwell/src/camera/GPhoto.vala:176
#3 0x0000000000615331 in import_page_load_previews_and_metadata (self=0x12d4570, import_list=0x142f040)
at /home/seiderer/Work/shotwell/shotwell/src/camera/ImportPage.vala:1405
#4 0x00000000006114d9 in import_page_refresh_camera (self=0x12d4570) at /home/seiderer/Work/shotwell/shotwell/src/camera/ImportPage.vala:1125
#5 0x000000000060fa85 in import_page_try_refreshing_camera (self=0x12d4570, fail_on_locked=0)
at /home/seiderer/Work/shotwell/shotwell/src/camera/ImportPage.vala:952
#6 0x000000000060f936 in import_page_real_switched_to (base=0x12d4570) at /home/seiderer/Work/shotwell/shotwell/src/camera/ImportPage.vala:943
...
(gdb) frame 1
#1 0x0000000000604c9a in gp_load_file_into_buffer (context=0x1911740, camera=0x194c950, folder=0x1873270 "/DCIM/100CANON", filename=0xe33a50 "IMG_0001.JPG",
filetype=GP_FILE_TYPE_EXIF, result_length1=0x7fffffffb1c0, error=0x7fffffffb1b8) at /home/seiderer/Work/shotwell/shotwell/src/camera/GPhoto.vala:248
248 Memory.copy(buffer, data, buffer.length);
(gdb) p buffer
$1 = (guint8 *) 0x1955110 ""
(gdb) p data
$2 = (guint8 *) 0x0
---> data (the location from where to copy) is null
(gdb) p buffer.length
Attempt to extract a component of a value that is not a structure.
---> gdb could not show vala data types, take a look at the compiled version of GPhoto.vala,
---> a generated C file src/camera/GPhoto.c where the memcpy takes place:
(gdb) p _tmp29_
$3 = (guint8 *) 0x1955110 ""
(gdb) p _tmp30_
$4 = (guint8 *) 0x0
---> _tmp30_/data is realy null (no gdb debug info failure)
(gdb) p _tmp31__length1
$5 = 21336
---> _tmp31__length1/buffer.length is set, so take a look at vala source code
(gdb) list
234
235 res = camera.get_file(folder, filename, filetype, camera_file, context);
236 if (res != Result.OK)
237 throw new GPhotoError.LIBRARY("[%d] Error retrieving file object for %s/%s: %s",
238 (int) res, folder, filename, res.as_string());
239
240 // if buffer can be loaded into memory, return a copy of that (can't return buffer itself
241 // as it will be destroyed when the camera_file is unref'd)
242 unowned uint8[] data;
243 res = camera_file.get_data_and_size(out data);
244 if (res != Result.OK)
245 return null;
246
247 uint8[] buffer = new uint8[data.length];
248 Memory.copy(buffer, data, buffer.length);
249
250 return buffer;
---> camera_file.get_data_and_size(out data) return code is checked, but data is null?
---> one more look at the generated C file
---> check the parameters for the gp_file_get_data_and_size(CameraFile*, const char **data, unsigned long int *size) call
(gdb) p _tmp24_
$6 = 0
---> return value is o.k.
(gdb) p _tmp22_
$7 = (guint8 *) 0x0
---> data is set to null
(gdb) p _tmp23_
$8 = 21336
---> size seems to be o.k.
---> what now? check the data types...
(gdb) ptype _tmp22_
type = unsigned char *
---> o.k.
(gdb) ptype _tmp23_
type = int
---> here it is what causes the bug, on x86_64 the type 'int' is 4 bytes long
---> and the type 'unsigned long' is 8 bytes
(gdb) p sizeof(int)
$9 = 4
(gdb) p sizeof(unsigned long)
$10 = 8
---> take a look at the addresse of _tmp22_ (data) and _tmp23_ (size)
(gdb) p &_tmp22_
$11 = (guint8 **) 0x7fffffffb008
(gdb) p &_tmp23_
$12 = (gint *) 0x7fffffffb004
---> what happens? From libgphoto2-2.4.11/libgphoto2/gphoto2-file.c
350 gp_file_get_data_and_size (CameraFile *file, const char **data,
351 unsigned long int *size)
352 {
353 CHECK_NULL (file);
354
355 switch (file->accesstype) {
356 case GP_FILE_ACCESSTYPE_MEMORY:
357 if (data)
358 *data = file->data;
359 if (size)
360 *size = file->size;
361 break;
---> first at line 358 file->data pointer/8 bytes are written to the adress &_tmp22_/0x7fffffffb008
---> second at line 360 file->size/8 bytes are written to the address & &_tmp23/0x7fffffffb004
---> overwriting 4 bytes of _tmp22_ (because of the type mismatch) which leads to the null pointer
---> in the memcopy
Suggested patch (fix libgphoto2/get_data_and_size() vala binding, adjust calls in src/camera/GPhoto.vala):
diff --git a/src/camera/GPhoto.vala b/src/camera/GPhoto.vala
index e2af2c8..c02a3fd 100644
--- a/src/camera/GPhoto.vala
+++ b/src/camera/GPhoto.vala
@@ -201,11 +201,12 @@ namespace GPhoto {
// if entire file fits in memory, return a stream from that ... can't merely wrap
// MemoryInputStream around the camera_file buffer, as that will be destroyed when the
// function returns
- unowned uint8[] data;
- res = camera_file.get_data_and_size(out data);
+ unowned uint8 *data;
+ ulong data_len;
+ res = camera_file.get_data_and_size(out data, out data_len);
if (res == Result.OK) {
- uint8[] buffer = new uint8[data.length];
- Memory.copy(buffer, data, data.length);
+ uint8[] buffer = new uint8[data_len];
+ Memory.copy(buffer, data, buffer.length);
// if buffer can be loaded into memory, return a copy of that (can't return buffer itself
// as it will be destroyed when the camera_file is unref'd)
- unowned uint8[] data;
- res = camera_file.get_data_and_size(out data);
+ unowned uint8 *data;
+ ulong data_len;
+ res = camera_file.get_data_and_size(out data, out data_len);
if (res != Result.OK)
return null;
- uint8[] buffer = new uint8[data.length];
+ uint8[] buffer = new uint8[data_len];
Same Problem found with Showwell-11.5 on openSUSE 12.1 (x86_64).
Problem analysis (gdb trace/comments):
$ gdb ./shotwell
(gdb) run
Program received signal SIGSEGV, Segmentation fault. file_into_ buffer (context=0x1911740, camera=0x194c950, folder=0x1873270 "/DCIM/100CANON", filename=0xe33a50 "IMG_0001.JPG", GP_FILE_ TYPE_EXIF, result_ length1= 0x7fffffffb1c0, error=0x7ffffff fb1b8) at /home/seiderer/ Work/shotwell/ shotwell/ src/camera/ GPhoto. vala:248 Work/shotwell/ shotwell/ src/camera/ GPhoto. vala:176 page_load_ previews_ and_metadata (self=0x12d4570, import_ list=0x142f040) Work/shotwell/ shotwell/ src/camera/ ImportPage. vala:1405 page_refresh_ camera (self=0x12d4570) at /home/seiderer/ Work/shotwell/ shotwell/ src/camera/ ImportPage. vala:1125 page_try_ refreshing_ camera (self=0x12d4570, fail_on_locked=0) Work/shotwell/ shotwell/ src/camera/ ImportPage. vala:952 page_real_ switched_ to (base=0x12d4570) at /home/seiderer/ Work/shotwell/ shotwell/ src/camera/ ImportPage. vala:943
0x00007ffff02b5540 in __memcpy_ssse3 () from /lib64/libc.so.6
(gdb) where
#0 0x00007ffff02b5540 in __memcpy_ssse3 () from /lib64/libc.so.6
#1 0x0000000000604c9a in gp_load_
filetype=
#2 0x0000000000603c87 in gp_load_metadata (context=0x1911740, camera=0x194c950, folder=0x1873270 "/DCIM/100CANON", filename=0xe33a50 "IMG_0001.JPG", error=
0x7fffffffb2a8) at /home/seiderer/
#3 0x0000000000615331 in import_
at /home/seiderer/
#4 0x00000000006114d9 in import_
#5 0x000000000060fa85 in import_
at /home/seiderer/
#6 0x000000000060f936 in import_
...
(gdb) frame 1 file_into_ buffer (context=0x1911740, camera=0x194c950, folder=0x1873270 "/DCIM/100CANON", filename=0xe33a50 "IMG_0001.JPG", GP_FILE_ TYPE_EXIF, result_ length1= 0x7fffffffb1c0, error=0x7ffffff fb1b8) at /home/seiderer/ Work/shotwell/ shotwell/ src/camera/ GPhoto. vala:248
#1 0x0000000000604c9a in gp_load_
filetype=
248 Memory.copy(buffer, data, buffer.length);
(gdb) p buffer
$1 = (guint8 *) 0x1955110 ""
(gdb) p data
$2 = (guint8 *) 0x0
---> data (the location from where to copy) is null
(gdb) p buffer.length
Attempt to extract a component of a value that is not a structure.
---> gdb could not show vala data types, take a look at the compiled version of GPhoto.vala,
---> a generated C file src/camera/GPhoto.c where the memcpy takes place:
2182 #line 248 "/home/ seiderer/ Work/shotwell/ shotwell/ src/camera/ GPhoto. vala" seiderer/ Work/shotwell/ shotwell/ src/camera/ GPhoto. vala" seiderer/ Work/shotwell/ shotwell/ src/camera/ GPhoto. vala"
2183 _tmp31__length1 = buffer_length1;
2184 #line 248 "/home/
2185 memcpy (_tmp29_, _tmp30_, (gsize) _tmp31__length1);
2186 #line 250 "/home/
(gdb) p _tmp29_
$3 = (guint8 *) 0x1955110 ""
(gdb) p _tmp30_
$4 = (guint8 *) 0x0
---> _tmp30_/data is realy null (no gdb debug info failure)
(gdb) p _tmp31__length1
$5 = 21336
---> _tmp31_ _length1/ buffer. length is set, so take a look at vala source code
(gdb) list get_file( folder, filename, filetype, camera_file, context); LIBRARY( "[%d] Error retrieving file object for %s/%s: %s", file.get_ data_and_ size(out data);
234
235 res = camera.
236 if (res != Result.OK)
237 throw new GPhotoError.
238 (int) res, folder, filename, res.as_string());
239
240 // if buffer can be loaded into memory, return a copy of that (can't return buffer itself
241 // as it will be destroyed when the camera_file is unref'd)
242 unowned uint8[] data;
243 res = camera_
244 if (res != Result.OK)
245 return null;
246
247 uint8[] buffer = new uint8[data.length];
248 Memory.copy(buffer, data, buffer.length);
249
250 return buffer;
---> camera_ file.get_ data_and_ size(out data) return code is checked, but data is null?
---> one more look at the generated C file
2123 #line 243 "/home/ seiderer/ Work/shotwell/ shotwell/ src/camera/ GPhoto. vala" seiderer/ Work/shotwell/ shotwell/ src/camera/ GPhoto. vala" get_data_ and_size (_tmp21_, &_tmp22_, &_tmp23_);
2124 _tmp21_ = camera_file;
2125 #line 243 "/home/
2126 _tmp24_ = gp_file_
---> check the parameters for the gp_file_ get_data_ and_size( CameraFile* , const char **data, unsigned long int *size) call
(gdb) p _tmp24_
$6 = 0
---> return value is o.k.
(gdb) p _tmp22_
$7 = (guint8 *) 0x0
---> data is set to null
(gdb) p _tmp23_
$8 = 21336
---> size seems to be o.k.
---> what now? check the data types...
(gdb) ptype _tmp22_
type = unsigned char *
---> o.k.
(gdb) ptype _tmp23_
type = int
---> here it is what causes the bug, on x86_64 the type 'int' is 4 bytes long
---> and the type 'unsigned long' is 8 bytes
(gdb) p sizeof(int)
$9 = 4
(gdb) p sizeof(unsigned long)
$10 = 8
---> take a look at the addresse of _tmp22_ (data) and _tmp23_ (size)
(gdb) p &_tmp22_
$11 = (guint8 **) 0x7fffffffb008
(gdb) p &_tmp23_
$12 = (gint *) 0x7fffffffb004
---> what happens? From libgphoto2- 2.4.11/ libgphoto2/ gphoto2- file.c
350 gp_file_ get_data_ and_size (CameraFile *file, const char **data, ACCESSTYPE_ MEMORY:
351 unsigned long int *size)
352 {
353 CHECK_NULL (file);
354
355 switch (file->accesstype) {
356 case GP_FILE_
357 if (data)
358 *data = file->data;
359 if (size)
360 *size = file->size;
361 break;
---> first at line 358 file->data pointer/8 bytes are written to the adress &_tmp22_ /0x7fffffffb008 0x7fffffffb004
---> second at line 360 file->size/8 bytes are written to the address & &_tmp23/
---> overwriting 4 bytes of _tmp22_ (because of the type mismatch) which leads to the null pointer
---> in the memcopy
Suggested patch (fix libgphoto2/ get_data_ and_size( ) vala binding, adjust calls in src/camera/ GPhoto. vala):
diff --git a/src/camera/ GPhoto. vala b/src/camera/ GPhoto. vala GPhoto. vala GPhoto. vala file.get_ data_and_ size(out data); file.get_ data_and_ size(out data, out data_len);
index e2af2c8..c02a3fd 100644
--- a/src/camera/
+++ b/src/camera/
@@ -201,11 +201,12 @@ namespace GPhoto {
// if entire file fits in memory, return a stream from that ... can't merely wrap
// MemoryInputStream around the camera_file buffer, as that will be destroyed when the
// function returns
- unowned uint8[] data;
- res = camera_
+ unowned uint8 *data;
+ ulong data_len;
+ res = camera_
if (res == Result.OK) {
- uint8[] buffer = new uint8[data.length];
- Memory.copy(buffer, data, data.length);
+ uint8[] buffer = new uint8[data_len];
+ Memory.copy(buffer, data, buffer.length);
return new MemoryInputStre am.from_ data(buffer, on_mins_destroyed);
}
@@ -239,12 +240,13 @@ namespace GPhoto {
// if buffer can be loaded into memory, return a copy of that (can't return buffer itself file.get_ data_and_ size(out data); file.get_ data_and_ size(out data, out data_len);
// as it will be destroyed when the camera_file is unref'd)
- unowned uint8[] data;
- res = camera_
+ unowned uint8 *data;
+ ulong data_len;
+ res = camera_
if (res != Result.OK)
return null;
- uint8[] buffer = new uint8[data.length];
+ uint8[] buffer = new uint8[data_len];