more fixes for sevenZip parser exception on specific archives

Found 2 more cases were modified code throws exceptions while original J7Zip
unpacks it.
Reimplemented error prone CoderMixer2ST from unmodified J7Zip.jar.
pull/46/head
reger 9 years ago
parent 826e6e5894
commit 51e7151591

Binary file not shown.

@ -51,37 +51,31 @@ public class BindInfo {
/**
* @param streamIndex
* @return int[2], where the element at index 0 specifies the coder index number and
* the element at index 1 is the stream index corresponding to the found coder index.
* <p>Returns <code>null</code> if no InStream for <code>streamIndex</code> could be
* found.</p>
* @return the coder index number
*/
public int[] FindInStream(int streamIndex) {
public int FindInStream(int streamIndex) {
for (int i=0; i<Coders.size(); i++) {
int curSize = ((CoderStreamsInfo)Coders.get(i)).NumInStreams;
if (streamIndex < curSize) {
return new int[] { i, streamIndex };
return i;
}
streamIndex -= curSize;
}
return null;
return -1; //throw new UnknownError("1");
}
/**
* @param streamIndex
* @return int[2], where the element at index 0 specifies the coder index number and
* the element at index 1 is the stream index corresponding to the found coder index.
* <p>Returns <code>null</code> if no OutStream for <code>streamIndex</code> could be
* found.</p>
* @return the coder index number
*/
public int[] FindOutStream(int streamIndex) {
public int FindOutStream(int streamIndex) {
for (int i=0; i<Coders.size(); i++) {
int curSize = ((CoderStreamsInfo)Coders.get(i)).NumOutStreams;
if (streamIndex < curSize)
return new int[] { i, streamIndex };
return i;
streamIndex -= curSize;
}
return null;
return -1; //throw new UnknownError("1");
}
public boolean equals(Object obj) {

@ -1,85 +1,86 @@
package SevenZip.Archive.Common;
import SevenZip.HRESULT;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import Common.LongVector;
import SevenZip.ICompressCoder2;
import SevenZip.ICompressCoder;
import SevenZip.ICompressSetInStream;
import SevenZip.ICompressSetOutStream;
import SevenZip.ICompressSetOutStreamSize;
import Common.LongVector;
import SevenZip.HRESULT;
import SevenZip.ICompressProgressInfo;
import SevenZip.ICompressSetInStream;
public class CoderMixer2ST implements ICompressCoder2, CoderMixer2 {
final BindInfo bindInfo;
Vector<STCoderInfo> coders = new Vector();
int mainCoderIndex;
public class CoderMixer2ST implements ICompressCoder2 , CoderMixer2 {
public CoderMixer2ST(BindInfo bindInfo) {
this.bindInfo = bindInfo;
}
BindInfo _bindInfo = new BindInfo();
Vector<STCoderInfo> _coders = new Vector<STCoderInfo>();
int _mainCoderIndex;
public void AddCoderCommon(boolean isMain) {
CoderStreamsInfo csi = (CoderStreamsInfo)bindInfo.Coders.get(coders.size());
coders.add(new STCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));
}
public CoderMixer2ST(BindInfo bindInfo) {
this._bindInfo = bindInfo;
}
public void AddCoder2(ICompressCoder2 coder, boolean isMain) {
AddCoderCommon(isMain);
coders.lastElement().Coder2 = coder;
}
public void AddCoderCommon(boolean isMain) {
CoderStreamsInfo csi = _bindInfo.Coders.get(_coders.size());
_coders.add(new STCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));
}
public void AddCoder2(ICompressCoder2 coder, boolean isMain) {
AddCoderCommon(isMain);
_coders.lastElement().Coder2 = coder;
}
public void AddCoder(ICompressCoder coder, boolean isMain) {
AddCoderCommon(isMain);
coders.lastElement().Coder = coder;
}
public void AddCoder(ICompressCoder coder, boolean isMain) {
AddCoderCommon(isMain);
_coders.lastElement().Coder = coder;
}
public void ReInit() {
}
@Override
public void ReInit() {
}
public void SetCoderInfo(int coderIndex, LongVector inSizes, LongVector outSizes) {
// _coders[coderIndex].SetCoderInfo(inSizes, outSizes);
coders.get(coderIndex).SetCoderInfo(inSizes, outSizes);
}
@Override
public void SetCoderInfo(int coderIndex,LongVector inSizes, LongVector outSizes) {
// _coders[coderIndex].SetCoderInfo(inSizes, outSizes);
_coders.get(coderIndex).SetCoderInfo(inSizes, outSizes);
}
public int GetInStream(
Vector<InputStream> inStreams,
//Object useless_inSizes, // const UInt64 **inSizes,
int streamIndex,
InputStream [] inStreamRes) {
java.io.InputStream seqInStream;
InputStream seqInStream;
int i;
for(i = 0; i < bindInfo.InStreams.size(); i++)
if (bindInfo.InStreams.get(i) == streamIndex) {
for(i = 0; i < _bindInfo.InStreams.size(); i++)
if (_bindInfo.InStreams.get(i) == streamIndex) {
seqInStream = inStreams.get(i);
inStreamRes[0] = seqInStream; // seqInStream.Detach();
return HRESULT.S_OK;
}
int binderIndex = bindInfo.FindBinderForInStream(streamIndex);
int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
if (binderIndex < 0)
return HRESULT.E_INVALIDARG;
int coderIndex = _bindInfo.FindOutStream(_bindInfo.BindPairs.get(binderIndex).OutIndex);
if (coderIndex < 0)
return HRESULT.E_INVALIDARG;
int tmp1[] = new int[2]; // TBD
//int tmp2 [] = new int[1]; // TBD
tmp1 = bindInfo.FindOutStream(bindInfo.BindPairs.get(binderIndex).OutIndex);
// , tmp1 /* coderIndex */ , tmp2 /* coderStreamIndex */ );
int coderIndex = tmp1[0], coderStreamIndex = tmp1[0];
CoderInfo coder = coders.get(coderIndex);
CoderInfo coder = _coders.get(coderIndex);
if (coder.Coder == null)
return HRESULT.E_NOTIMPL;
seqInStream = (java.io.InputStream)coder.Coder; // coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
seqInStream = (InputStream)coder.Coder; // coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
if (seqInStream == null)
return HRESULT.E_NOTIMPL;
int startIndex = bindInfo.GetCoderInStreamIndex(coderIndex);
int startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);
if (coder.Coder == null)
return HRESULT.E_NOTIMPL;
@ -91,7 +92,7 @@ public class CoderMixer2ST implements ICompressCoder2, CoderMixer2 {
if (coder.NumInStreams > 1)
return HRESULT.E_NOTIMPL;
for (i = 0; i < (int)coder.NumInStreams; i++) {
InputStream [] tmp = new java.io.InputStream[1];
InputStream [] tmp = new InputStream[1];
int res = GetInStream(inStreams, /*useless_inSizes,*/ startIndex + i, tmp /* &seqInStream2 */ );
if (res != HRESULT.S_OK) return res;
InputStream seqInStream2 = tmp[0];
@ -102,92 +103,168 @@ public class CoderMixer2ST implements ICompressCoder2, CoderMixer2 {
return HRESULT.S_OK;
}
public void Code(
Vector<InputStream> inStreams,
//Object useless_inSizes, // const UInt64 ** inSizes ,
int numInStreams,
Vector<OutputStream> outStreams,
//Object useless_outSizes, // const UInt64 ** /* outSizes */,
int numOutStreams,
ICompressProgressInfo progress) throws IOException {
if (numInStreams != bindInfo.InStreams.size() || numOutStreams != bindInfo.OutStreams.size())
throw new IllegalArgumentException("internal error: numInStreams != _bindInfo.InStreams.size() || numOutStreams != _bindInfo.OutStreams.size()");
// Find main coder
int mainCoderIndex = -1;
for (int i=0; i<coders.size(); i++)
if ((coders.get(i)).IsMain) {
mainCoderIndex = i;
break;
}
if (mainCoderIndex < 0)
for (int i=0; i<coders.size(); i++)
if ((coders.get(i)).NumInStreams > 1) {
if (mainCoderIndex >= 0) // TODO: description, what exactly is not implemented
throw new IOException("not implemented");
mainCoderIndex = i;
}
if (mainCoderIndex < 0)
mainCoderIndex = 0;
// _mainCoderIndex = 0;
// _mainCoderIndex = _coders.Size() - 1;
CoderInfo mainCoder = coders.get(mainCoderIndex);
Vector<InputStream> seqInStreams = new Vector(); // CObjectVector< CMyComPtr<ISequentialInStream> >
int startInIndex = bindInfo.GetCoderInStreamIndex(mainCoderIndex);
// this original (from J7Zip 4.43a) replaces blows loop, as with LZMA BCJ2 format seqInStreams.size() is incorrect (array out of index) with modified code
for (int i = 0; i < (int)mainCoder.NumInStreams; i++) {
java.io.InputStream tmp [] = new java.io.InputStream[1];
public int GetOutStream(
Vector<OutputStream> outStreams,
//Object useless_outSizes, // const UInt64 **outSizes,
int streamIndex,
OutputStream [] outStreamRes) {
OutputStream seqOutStream;
int i;
for(i = 0; i < _bindInfo.OutStreams.size(); i++)
if (_bindInfo.OutStreams.get(i) == streamIndex) {
seqOutStream = outStreams.get(i);
outStreamRes[0] = seqOutStream; // seqOutStream.Detach();
return HRESULT.S_OK;
}
int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
if (binderIndex < 0)
return HRESULT.E_INVALIDARG;
int coderIndex = _bindInfo.FindInStream(_bindInfo.BindPairs.get(binderIndex).InIndex);
if (coderIndex < 0 )
return HRESULT.E_INVALIDARG;
CoderInfo coder = _coders.get(coderIndex);
if (coder.Coder == null)
return HRESULT.E_NOTIMPL;
try
{
seqOutStream = (OutputStream)coder.Coder; // coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
} catch (java.lang.ClassCastException e) {
return HRESULT.E_NOTIMPL;
}
int startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
if (coder.Coder == null)
return HRESULT.E_NOTIMPL;
ICompressSetOutStream setOutStream = null;
try {
setOutStream = (ICompressSetOutStream)coder.Coder; // coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
} catch (java.lang.ClassCastException e) {
return HRESULT.E_NOTIMPL;
}
if (coder.NumOutStreams > 1)
return HRESULT.E_NOTIMPL;
for (i = 0; i < (int)coder.NumOutStreams; i++) {
OutputStream [] tmp = new OutputStream[1];
int res = GetOutStream(outStreams, /*useless_outSizes,*/ startIndex + i, tmp /* &seqOutStream2 */ );
if (res != HRESULT.S_OK) return res;
OutputStream seqOutStream2 = tmp[0];
res = setOutStream.SetOutStream(seqOutStream2);
if (res != HRESULT.S_OK) return res;
}
outStreamRes[0] = seqOutStream; // seqOutStream.Detach();
return HRESULT.S_OK;
}
@Override
public int Code(
Vector<InputStream> inStreams,
//Object useless_inSizes, // const UInt64 ** inSizes ,
int numInStreams,
Vector<OutputStream> outStreams,
//Object useless_outSizes, // const UInt64 ** /* outSizes */,
int numOutStreams,
ICompressProgressInfo progress) throws IOException {
if (numInStreams != _bindInfo.InStreams.size() ||
numOutStreams != _bindInfo.OutStreams.size())
return HRESULT.E_INVALIDARG;
// Find main coder
int _mainCoderIndex = -1;
int i;
for (i = 0; i < _coders.size(); i++)
if (_coders.get(i).IsMain) {
_mainCoderIndex = i;
break;
}
if (_mainCoderIndex < 0)
for (i = 0; i < _coders.size(); i++)
if (_coders.get(i).NumInStreams > 1) {
if (_mainCoderIndex >= 0)
return HRESULT.E_NOTIMPL;
_mainCoderIndex = i;
}
if (_mainCoderIndex < 0)
_mainCoderIndex = 0;
// _mainCoderIndex = 0;
// _mainCoderIndex = _coders.Size() - 1;
CoderInfo mainCoder = _coders.get(_mainCoderIndex);
Vector<InputStream> seqInStreams = new Vector<InputStream>(); // CObjectVector< CMyComPtr<ISequentialInStream> >
Vector<OutputStream> seqOutStreams = new Vector<OutputStream>(); // CObjectVector< CMyComPtr<ISequentialOutStream> >
int startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);
int startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);
for (i = 0; i < (int)mainCoder.NumInStreams; i++) {
InputStream tmp [] = new InputStream[1];
int res = GetInStream(inStreams, /*useless_inSizes,*/ startInIndex + i, tmp /* &seqInStream */ );
if (res != HRESULT.S_OK) return;
java.io.InputStream seqInStream = tmp[0];
if (res != HRESULT.S_OK) return res;
InputStream seqInStream = tmp[0];
seqInStreams.add(seqInStream);
}
/* --- replaced by above ---
for (int i=0; i<mainCoder.NumInStreams; i++)
for (int j=0; j<bindInfo.InStreams.size(); j++)
if (bindInfo.InStreams.get(j) == startInIndex + i)
seqInStreams.add(inStreams.get(j));
*/
Vector<OutputStream> seqOutStreams = new Vector(); // CObjectVector< CMyComPtr<ISequentialOutStream> >
int startOutIndex = bindInfo.GetCoderOutStreamIndex(mainCoderIndex);
for (int i=0; i<mainCoder.NumOutStreams; i++)
for (int j=0; j<bindInfo.OutStreams.size(); j++)
if (bindInfo.OutStreams.get(j) == startOutIndex + i)
seqOutStreams.add(outStreams.get(j));
for (int i=0; i<coders.size(); i++) {
if (i == mainCoderIndex) continue;
CoderInfo coder = coders.get(i);
((ICompressSetOutStreamSize)coder.Coder).SetOutStreamSize(coder.OutSizePointers.Front());
}
if (mainCoder.Coder != null) {
mainCoder.Coder.Code(
seqInStreams.firstElement(),
seqOutStreams.firstElement(),
mainCoder.OutSizePointers.Front(),
progress);
} else {
mainCoder.Coder2.Code(
seqInStreams,
//new Long(mainCoder.InSizePointers.Front()),
mainCoder.NumInStreams,
seqOutStreams,
//new Long(mainCoder.OutSizePointers.Front()),
mainCoder.NumOutStreams,
progress);
}
OutputStream stream = seqOutStreams.firstElement();
if (stream != null) stream.flush();
}
public void close() {
}
for (i = 0; i < (int)mainCoder.NumOutStreams; i++) {
OutputStream tmp [] = new OutputStream[1];
int res = GetOutStream(outStreams, /*useless_outSizes,*/ startOutIndex + i, tmp);
if (res != HRESULT.S_OK) return res;
OutputStream seqOutStream = tmp[0];
seqOutStreams.add(seqOutStream);
}
Vector<InputStream> seqInStreamsSpec = new Vector<InputStream>();
Vector<OutputStream> seqOutStreamsSpec = new Vector<OutputStream>();
for (i = 0; i < (int)mainCoder.NumInStreams; i++)
seqInStreamsSpec.add(seqInStreams.get(i));
for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
seqOutStreamsSpec.add(seqOutStreams.get(i));
for (i = 0; i < _coders.size(); i++) {
if (i == _mainCoderIndex)
continue;
CoderInfo coder = _coders.get(i);
ICompressSetOutStreamSize setOutStreamSize = null;
try
{
setOutStreamSize = (ICompressSetOutStreamSize)coder.Coder;
/*int res =*/ setOutStreamSize.SetOutStreamSize(coder.OutSizePointers.get(0));
//if (res != HRESULT.S_OK) return res;
} catch (java.lang.ClassCastException e) {
// nothing to do
}
}
if (mainCoder.Coder != null) {
/*int res =*/ mainCoder.Coder.Code(
seqInStreamsSpec.get(0),
seqOutStreamsSpec.get(0),
// TBD mainCoder.InSizePointers.get(0),
mainCoder.OutSizePointers.get(0),
progress);
//if (res != HRESULT.S_OK) return res;
} else {
/*int res =*/ mainCoder.Coder2.Code(
seqInStreamsSpec, // &seqInStreamsSpec.Front(
//mainCoder.InSizePointers.Front(), // &mainCoder.InSizePointers.Front()
mainCoder.NumInStreams,
seqOutStreamsSpec, // &seqOutStreamsSpec.Front()
//mainCoder.OutSizePointers.Front(), // &mainCoder.OutSizePointers.Front()
mainCoder.NumOutStreams,
progress);
//if (res != HRESULT.S_OK) return res;
}
OutputStream stream = seqOutStreams.firstElement();
stream.flush();
return HRESULT.S_OK;
}
@Override
public void close() {
}
}

@ -7,10 +7,10 @@ import java.io.OutputStream;
import java.util.Vector;
import SevenZip.Compression.LZ.OutWindow;
import SevenZip.ICompressCoder2;
import SevenZip.ICompressProgressInfo;
import SevenZip.Common.InBuffer;
import SevenZip.HRESULT;
public class BCJ2_x86_Decoder implements ICompressCoder2 {
@ -32,7 +32,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
// return ((b0 == 0x0F) && ((b1 & 0xF0) == 0x80));
// }
void CodeReal(
int CodeReal(
Vector<InputStream> inStreams,
//Object useless1, // const UInt64 ** /* inSizes */,
int numInStreams,
@ -83,7 +83,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
int b = _mainInStream.read();
if (b == -1) {
Flush();
return;
return HRESULT.S_OK;
}
_outStream.WriteByte(b); // System.out.println("0:"+b);
// if ((b != 0xE8) && (b != 0xE9) && (!IsJcc(prevByte, b))) {
@ -116,7 +116,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
src |= ((int)b0) << 8;
b0 = _callStream.read();
if (b0 == -1) return; // TODO: HRESULT.S_FALSE;
if (b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0);
} else {
@ -133,7 +133,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
src |= ((int)b0) << 8;
b0 = _jumpStream.read();
if(b0 == -1) return; // TODO: HRESULT.S_FALSE;
if(b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0);
}
@ -153,7 +153,8 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
_outStream.Flush();
}
public void Code(
@Override
public int Code(
Vector<InputStream> inStreams, // ISequentialInStream **inStreams,
//Object useless_inSizes, // const UInt64 ** /* inSizes */,
int numInStreams,
@ -163,7 +164,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
ICompressProgressInfo progress) throws java.io.IOException {
try {
CodeReal(inStreams, /*useless_inSizes,*/ numInStreams,
return CodeReal(inStreams, /*useless_inSizes,*/ numInStreams,
outStreams, /*useless_outSizes,*/ numOutStreams, progress);
} catch(java.io.IOException e) {
throw e;
@ -180,6 +181,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
_outStream.ReleaseStream();
}
@Override
public void close() throws java.io.IOException {
ReleaseStreams();
}

@ -7,7 +7,7 @@ import java.util.Vector;
public interface ICompressCoder2 {
public void Code(
public int Code(
Vector<InputStream> inStreams,
//Object useless1, // const UInt64 ** /* inSizes */,
int numInStreams,

Loading…
Cancel
Save