Hi all,
I've been beating up on the 1.1 tarball so I could make
the Solaris package, and came across a rather nasty memory
corruption problem.
My sanity check of the build died when I clicked on any
image in my library, with this info:
$ mdb /opt/darktable/bin/darktable
> :r -v
[mipmap_cache] cache is empty, file
`/home/jmcp/.cache/darktable/mipmaps-2c30cb4285311a3eb3dd7b0daf9b4c5f8f666440'
doesn't exist
umem allocator: redzone violation: write past end of buffer
buffer=3f687a60 bufctl=3f689178 cache: umem_alloc_16
previous transaction on buffer 3f687a60:
thread=4 time=T-0.003466117 slab=3f635d30 cache: umem_alloc_16
libumem.so.1'umem_cache_alloc_debug+0x157
libumem.so.1'umem_cache_alloc+0x157
libumem.so.1'umem_alloc+0xd0
libumem.so.1'malloc+0x2d
libumem.so.1'calloc+0x63
libdarktable.so'monotone_hermite_set+0x7e
libdarktable.so'interpolate_set+0x32
libdarktable.so'CurveDataSample+0x48e
libbasecurve.so'commit_params+0x145
libbasecurve.so'init_pipe+0x65
libdarktable.so'dt_iop_init_pipe+0x3a
libdarktable.so'dt_dev_pixelpipe_create_nodes+0xeb
libdarktable.so'dt_imageio_export_with_flags+0x170
libdarktable.so'_init_8.isra.8+0x1a7
libdarktable.so'dt_mipmap_cache_read_get+0x449
umem: heap corruption detected
stack trace:
libumem.so.1'umem_err_recoverable+0x42
libumem.so.1'umem_error+0x510
libumem.so.1'umem_free+0x11b
libumem.so.1'process_free+0x57
libumem.so.1'free+0x1e
libdarktable.so'CurveDataSample+0x54a
libbasecurve.so'commit_params+0x145
libbasecurve.so'init_pipe+0x65
libdarktable.so'dt_iop_init_pipe+0x3a
libdarktable.so'dt_dev_pixelpipe_create_nodes+0xeb
libdarktable.so'dt_imageio_export_with_flags+0x170
libdarktable.so'_init_8.isra.8+0x1a7
libdarktable.so'dt_mipmap_cache_read_get+0x449
libdarktable.so'dt_image_load_job_run+0x4b
libdarktable.so'dt_control_run_job+0x21c
libdarktable.so'dt_control_work+0x41
libc.so.1'_thrp_setup+0x9d
libc.so.1'_lwp_start+0x0
mdb: stop on SIGABRT
libumem is a memory allocation library which provides some protection
for your application and is very useful to help nail down errors like
this.
I eventually tracked the problem to this part of monotone_hermite_set
(in src/common/curve_tools.c):
440 for (i=0; i<n; i++)
441 {
442 if (fabs(delta[i]) < EPSILON)
443 {
444 m[i] = 0.0f;
445 m[i+1] = 0.0f;
446 }
447 else
448 {
449 const float alpha = m[i]/delta[i];
450 const float beta = m[i+1]/delta[i];
451 const float tau = alpha*alpha+beta*beta;
452 if (tau > 9.0f)
453 {
454 m[i] = 3.0f*alpha*delta[i]/sqrtf(tau);
455 m[i+1] = 3.0f*beta*delta[i]/sqrtf(tau);
456 }
457 }
458 }
'm' is allocated to be 'n' * sizeof(float). Which is
great until line 455 - when i = n-1, we then blat a number
into m[n], which exceeds the limit of the array.
Changing #424 to be an 'n+1' allocation makes the problem
go away.
424 m = (float *)calloc(n+1,sizeof(float));
On a tangent (haha), I believe it's more efficient for the
variables alpha, beta and tau to be declared outside the
for loop so that we avoid possible stupidity from the compiler
and setup/teardown costs. Not anywhere near as important
as line 424, however.
James C. McPherson
--
Solaris kernel software engineer, system admin and troubleshooter
http://www.jmcpdotcom.com/blog
Find me on LinkedIn @ http://www.linkedin.com/in/jamescmcpherson
------------------------------------------------------------------------------
Keep yourself connected to Go Parallel:
INSIGHTS What's next for parallel hardware, programming and related areas?
Interviews and blogs by thought leaders keep you ahead of the curve.
http://goparallel.sourceforge.net
_______________________________________________
darktable-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/darktable-devel