Skip to content

Commit 75bf857

Browse files
committed
#3884 Crash in kdu_core::kdu_params::get
1 parent 1df890d commit 75bf857

File tree

1 file changed

+99
-84
lines changed

1 file changed

+99
-84
lines changed

indra/llkdu/llimagej2ckdu.cpp

Lines changed: 99 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -279,103 +279,118 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
279279
{
280280
LLImageDataLock lock(&base);
281281

282-
S32 data_size = base.getDataSize();
283-
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
282+
try
283+
{
284284

285-
//
286-
// Initialization
287-
//
288-
mCodeStreamp.reset();
285+
S32 data_size = base.getDataSize();
286+
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
289287

290-
// It's not clear to nat under what circumstances we would reuse a
291-
// pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
292-
// two U32s and a pointer, so it's not as if it would be a huge overhead
293-
// to allocate a new one every time.
294-
// Also -- why is base.getData() tested specifically here? If that returns
295-
// NULL, shouldn't we bail out of the whole method?
296-
if (!mInputp && base.getData())
297-
{
298-
// The compressed data has been loaded
299-
// Setup the source for the codestream
300-
mInputp.reset(new LLKDUMemSource(base.getData(), data_size));
301-
}
288+
//
289+
// Initialization
290+
//
291+
mCodeStreamp.reset();
302292

303-
if (mInputp)
304-
{
305-
// This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset().
306-
mInputp->reset();
307-
}
293+
// It's not clear to nat under what circumstances we would reuse a
294+
// pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
295+
// two U32s and a pointer, so it's not as if it would be a huge overhead
296+
// to allocate a new one every time.
297+
// Also -- why is base.getData() tested specifically here? If that returns
298+
// NULL, shouldn't we bail out of the whole method?
299+
if (!mInputp && base.getData())
300+
{
301+
// The compressed data has been loaded
302+
// Setup the source for the codestream
303+
mInputp.reset(new LLKDUMemSource(base.getData(), data_size));
304+
}
308305

309-
mCodeStreamp->create(mInputp.get());
310-
311-
// Set the maximum number of bytes to use from the codestream
312-
// *TODO: This seems to be wrong. The base class should have no idea of
313-
// how j2c compression works so no good way of computing what's the byte
314-
// range to be used.
315-
mCodeStreamp->set_max_bytes(max_bytes,true);
316-
317-
// If you want to flip or rotate the image for some reason, change
318-
// the resolution, or identify a restricted region of interest, this is
319-
// the place to do it. You may use "kdu_codestream::change_appearance"
320-
// and "kdu_codestream::apply_input_restrictions" for this purpose.
321-
// If you wish to truncate the code-stream prior to decompression, you
322-
// may use "kdu_codestream::set_max_bytes".
323-
// If you wish to retain all compressed data so that the material
324-
// can be decompressed multiple times, possibly with different appearance
325-
// parameters, you should call "kdu_codestream::set_persistent" here.
326-
// There are a variety of other features which must be enabled at
327-
// this point if you want to take advantage of them. See the
328-
// descriptions appearing with the "kdu_codestream" interface functions
329-
// in "kdu_compressed.h" for an itemized account of these capabilities.
330-
331-
switch (mode)
332-
{
333-
case MODE_FAST:
334-
mCodeStreamp->set_fast();
335-
break;
336-
case MODE_RESILIENT:
337-
mCodeStreamp->set_resilient();
338-
break;
339-
case MODE_FUSSY:
340-
mCodeStreamp->set_fussy();
341-
break;
342-
default:
343-
llassert(0);
344-
mCodeStreamp->set_fast();
345-
}
306+
if (mInputp)
307+
{
308+
// This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset().
309+
mInputp->reset();
310+
}
346311

347-
kdu_dims dims;
348-
mCodeStreamp->get_dims(0,dims);
312+
mCodeStreamp->create(mInputp.get());
313+
314+
// Set the maximum number of bytes to use from the codestream
315+
// *TODO: This seems to be wrong. The base class should have no idea of
316+
// how j2c compression works so no good way of computing what's the byte
317+
// range to be used.
318+
mCodeStreamp->set_max_bytes(max_bytes, true);
319+
320+
// If you want to flip or rotate the image for some reason, change
321+
// the resolution, or identify a restricted region of interest, this is
322+
// the place to do it. You may use "kdu_codestream::change_appearance"
323+
// and "kdu_codestream::apply_input_restrictions" for this purpose.
324+
// If you wish to truncate the code-stream prior to decompression, you
325+
// may use "kdu_codestream::set_max_bytes".
326+
// If you wish to retain all compressed data so that the material
327+
// can be decompressed multiple times, possibly with different appearance
328+
// parameters, you should call "kdu_codestream::set_persistent" here.
329+
// There are a variety of other features which must be enabled at
330+
// this point if you want to take advantage of them. See the
331+
// descriptions appearing with the "kdu_codestream" interface functions
332+
// in "kdu_compressed.h" for an itemized account of these capabilities.
333+
334+
switch (mode)
335+
{
336+
case MODE_FAST:
337+
mCodeStreamp->set_fast();
338+
break;
339+
case MODE_RESILIENT:
340+
mCodeStreamp->set_resilient();
341+
break;
342+
case MODE_FUSSY:
343+
mCodeStreamp->set_fussy();
344+
break;
345+
default:
346+
llassert(0);
347+
mCodeStreamp->set_fast();
348+
}
349+
350+
kdu_dims dims;
351+
mCodeStreamp->get_dims(0, dims);
349352

350-
S32 components = mCodeStreamp->get_num_components();
353+
S32 components = mCodeStreamp->get_num_components();
351354

352-
// Check that components have consistent dimensions (for PPM file)
353-
for (int idx = 1; idx < components; ++idx)
354-
{
355-
kdu_dims other_dims;
356-
mCodeStreamp->get_dims(idx, other_dims);
357-
if (other_dims != dims)
355+
// Check that components have consistent dimensions (for PPM file)
356+
for (int idx = 1; idx < components; ++idx)
358357
{
359-
// This method is only called from methods that catch KDUError.
360-
// We want to fail the image load, not crash the viewer.
361-
LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
362-
<< stringize(other_dims)
363-
<< " do not match component 0 dimensions "
364-
<< stringize(dims) << "!")));
358+
kdu_dims other_dims;
359+
mCodeStreamp->get_dims(idx, other_dims);
360+
if (other_dims != dims)
361+
{
362+
// This method is only called from methods that catch KDUError.
363+
// We want to fail the image load, not crash the viewer.
364+
LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
365+
<< stringize(other_dims)
366+
<< " do not match component 0 dimensions "
367+
<< stringize(dims) << "!")));
368+
}
365369
}
366-
}
367370

368-
// Get the number of resolution levels in that image
369-
mLevels = mCodeStreamp->get_min_dwt_levels();
371+
// Get the number of resolution levels in that image
372+
mLevels = mCodeStreamp->get_min_dwt_levels();
370373

371-
// Set the base dimensions
372-
base.setSize(dims.size.x, dims.size.y, components);
373-
base.setLevels(mLevels);
374+
// Set the base dimensions
375+
base.setSize(dims.size.x, dims.size.y, components);
376+
base.setLevels(mLevels);
374377

375-
if (!keep_codestream)
378+
if (!keep_codestream)
379+
{
380+
mCodeStreamp.reset();
381+
mInputp.reset();
382+
}
383+
}
384+
catch (std::bad_alloc&)
376385
{
377-
mCodeStreamp.reset();
378-
mInputp.reset();
386+
// we are in a thread, can't show an 'out of memory' here,
387+
// main thread will keep going
388+
throw;
389+
}
390+
catch (...)
391+
{
392+
LLTHROW(KDUError(STRINGIZE("Unknown J2C error : " +
393+
boost::current_exception_diagnostic_information() << "!")));
379394
}
380395
}
381396

0 commit comments

Comments
 (0)