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 * @param streamIndex
* @return int[2], where the element at index 0 specifies the coder index number and * @return the coder index number
* 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>
*/ */
public int[] FindInStream(int streamIndex) { public int FindInStream(int streamIndex) {
for (int i=0; i<Coders.size(); i++) { for (int i=0; i<Coders.size(); i++) {
int curSize = ((CoderStreamsInfo)Coders.get(i)).NumInStreams; int curSize = ((CoderStreamsInfo)Coders.get(i)).NumInStreams;
if (streamIndex < curSize) { if (streamIndex < curSize) {
return new int[] { i, streamIndex }; return i;
} }
streamIndex -= curSize; streamIndex -= curSize;
} }
return null; return -1; //throw new UnknownError("1");
} }
/** /**
* @param streamIndex * @param streamIndex
* @return int[2], where the element at index 0 specifies the coder index number and * @return the coder index number
* 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>
*/ */
public int[] FindOutStream(int streamIndex) { public int FindOutStream(int streamIndex) {
for (int i=0; i<Coders.size(); i++) { for (int i=0; i<Coders.size(); i++) {
int curSize = ((CoderStreamsInfo)Coders.get(i)).NumOutStreams; int curSize = ((CoderStreamsInfo)Coders.get(i)).NumOutStreams;
if (streamIndex < curSize) if (streamIndex < curSize)
return new int[] { i, streamIndex }; return i;
streamIndex -= curSize; streamIndex -= curSize;
} }
return null; return -1; //throw new UnknownError("1");
} }
public boolean equals(Object obj) { public boolean equals(Object obj) {

@ -1,85 +1,86 @@
package SevenZip.Archive.Common; package SevenZip.Archive.Common;
import SevenZip.HRESULT;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Vector; import java.util.Vector;
import Common.LongVector;
import SevenZip.ICompressCoder2; import SevenZip.ICompressCoder2;
import SevenZip.ICompressCoder; import SevenZip.ICompressCoder;
import SevenZip.ICompressSetInStream;
import SevenZip.ICompressSetOutStream;
import SevenZip.ICompressSetOutStreamSize; import SevenZip.ICompressSetOutStreamSize;
import Common.LongVector;
import SevenZip.HRESULT;
import SevenZip.ICompressProgressInfo; import SevenZip.ICompressProgressInfo;
import SevenZip.ICompressSetInStream;
public class CoderMixer2ST implements ICompressCoder2, CoderMixer2 {
public class CoderMixer2ST implements ICompressCoder2 , CoderMixer2 {
final BindInfo bindInfo;
Vector<STCoderInfo> coders = new Vector(); BindInfo _bindInfo = new BindInfo();
int mainCoderIndex; Vector<STCoderInfo> _coders = new Vector<STCoderInfo>();
int _mainCoderIndex;
public CoderMixer2ST(BindInfo bindInfo) {
this.bindInfo = bindInfo; public CoderMixer2ST(BindInfo bindInfo) {
} this._bindInfo = bindInfo;
}
public void AddCoderCommon(boolean isMain) {
CoderStreamsInfo csi = (CoderStreamsInfo)bindInfo.Coders.get(coders.size()); public void AddCoderCommon(boolean isMain) {
coders.add(new STCoderInfo(csi.NumInStreams, csi.NumOutStreams, 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); public void AddCoder2(ICompressCoder2 coder, boolean isMain) {
coders.lastElement().Coder2 = coder; AddCoderCommon(isMain);
} _coders.lastElement().Coder2 = coder;
}
public void AddCoder(ICompressCoder coder, boolean isMain) {
AddCoderCommon(isMain); public void AddCoder(ICompressCoder coder, boolean isMain) {
coders.lastElement().Coder = coder; 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( public int GetInStream(
Vector<InputStream> inStreams, Vector<InputStream> inStreams,
//Object useless_inSizes, // const UInt64 **inSizes, //Object useless_inSizes, // const UInt64 **inSizes,
int streamIndex, int streamIndex,
InputStream [] inStreamRes) { InputStream [] inStreamRes) {
java.io.InputStream seqInStream; InputStream seqInStream;
int i; int i;
for(i = 0; i < bindInfo.InStreams.size(); i++) for(i = 0; i < _bindInfo.InStreams.size(); i++)
if (bindInfo.InStreams.get(i) == streamIndex) { if (_bindInfo.InStreams.get(i) == streamIndex) {
seqInStream = inStreams.get(i); seqInStream = inStreams.get(i);
inStreamRes[0] = seqInStream; // seqInStream.Detach(); inStreamRes[0] = seqInStream; // seqInStream.Detach();
return HRESULT.S_OK; return HRESULT.S_OK;
} }
int binderIndex = bindInfo.FindBinderForInStream(streamIndex); int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
if (binderIndex < 0) if (binderIndex < 0)
return HRESULT.E_INVALIDARG; 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 CoderInfo coder = _coders.get(coderIndex);
//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);
if (coder.Coder == null) if (coder.Coder == null)
return HRESULT.E_NOTIMPL; 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) if (seqInStream == null)
return HRESULT.E_NOTIMPL; return HRESULT.E_NOTIMPL;
int startIndex = bindInfo.GetCoderInStreamIndex(coderIndex); int startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);
if (coder.Coder == null) if (coder.Coder == null)
return HRESULT.E_NOTIMPL; return HRESULT.E_NOTIMPL;
@ -91,7 +92,7 @@ public class CoderMixer2ST implements ICompressCoder2, CoderMixer2 {
if (coder.NumInStreams > 1) if (coder.NumInStreams > 1)
return HRESULT.E_NOTIMPL; return HRESULT.E_NOTIMPL;
for (i = 0; i < (int)coder.NumInStreams; i++) { 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 */ ); int res = GetInStream(inStreams, /*useless_inSizes,*/ startIndex + i, tmp /* &seqInStream2 */ );
if (res != HRESULT.S_OK) return res; if (res != HRESULT.S_OK) return res;
InputStream seqInStream2 = tmp[0]; InputStream seqInStream2 = tmp[0];
@ -102,92 +103,168 @@ public class CoderMixer2ST implements ICompressCoder2, CoderMixer2 {
return HRESULT.S_OK; return HRESULT.S_OK;
} }
public void Code( public int GetOutStream(
Vector<InputStream> inStreams, Vector<OutputStream> outStreams,
//Object useless_inSizes, // const UInt64 ** inSizes , //Object useless_outSizes, // const UInt64 **outSizes,
int numInStreams, int streamIndex,
Vector<OutputStream> outStreams, OutputStream [] outStreamRes) {
//Object useless_outSizes, // const UInt64 ** /* outSizes */, OutputStream seqOutStream;
int numOutStreams, int i;
ICompressProgressInfo progress) throws IOException { for(i = 0; i < _bindInfo.OutStreams.size(); i++)
if (numInStreams != bindInfo.InStreams.size() || numOutStreams != bindInfo.OutStreams.size()) if (_bindInfo.OutStreams.get(i) == streamIndex) {
throw new IllegalArgumentException("internal error: numInStreams != _bindInfo.InStreams.size() || numOutStreams != _bindInfo.OutStreams.size()"); seqOutStream = outStreams.get(i);
outStreamRes[0] = seqOutStream; // seqOutStream.Detach();
// Find main coder return HRESULT.S_OK;
int mainCoderIndex = -1; }
for (int i=0; i<coders.size(); i++) int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
if ((coders.get(i)).IsMain) { if (binderIndex < 0)
mainCoderIndex = i; return HRESULT.E_INVALIDARG;
break;
} int coderIndex = _bindInfo.FindInStream(_bindInfo.BindPairs.get(binderIndex).InIndex);
if (coderIndex < 0 )
if (mainCoderIndex < 0) return HRESULT.E_INVALIDARG;
for (int i=0; i<coders.size(); i++)
if ((coders.get(i)).NumInStreams > 1) { CoderInfo coder = _coders.get(coderIndex);
if (mainCoderIndex >= 0) // TODO: description, what exactly is not implemented if (coder.Coder == null)
throw new IOException("not implemented"); return HRESULT.E_NOTIMPL;
mainCoderIndex = i;
} try
{
if (mainCoderIndex < 0) seqOutStream = (OutputStream)coder.Coder; // coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
mainCoderIndex = 0; } catch (java.lang.ClassCastException e) {
return HRESULT.E_NOTIMPL;
// _mainCoderIndex = 0; }
// _mainCoderIndex = _coders.Size() - 1;
CoderInfo mainCoder = coders.get(mainCoderIndex); int startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
Vector<InputStream> seqInStreams = new Vector(); // CObjectVector< CMyComPtr<ISequentialInStream> > if (coder.Coder == null)
int startInIndex = bindInfo.GetCoderInStreamIndex(mainCoderIndex); return HRESULT.E_NOTIMPL;
// 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 ICompressSetOutStream setOutStream = null;
for (int i = 0; i < (int)mainCoder.NumInStreams; i++) { try {
java.io.InputStream tmp [] = new java.io.InputStream[1]; 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 */ ); int res = GetInStream(inStreams, /*useless_inSizes,*/ startInIndex + i, tmp /* &seqInStream */ );
if (res != HRESULT.S_OK) return; if (res != HRESULT.S_OK) return res;
java.io.InputStream seqInStream = tmp[0]; InputStream seqInStream = tmp[0];
seqInStreams.add(seqInStream); seqInStreams.add(seqInStream);
} }
/* --- replaced by above --- for (i = 0; i < (int)mainCoder.NumOutStreams; i++) {
for (int i=0; i<mainCoder.NumInStreams; i++) OutputStream tmp [] = new OutputStream[1];
for (int j=0; j<bindInfo.InStreams.size(); j++) int res = GetOutStream(outStreams, /*useless_outSizes,*/ startOutIndex + i, tmp);
if (bindInfo.InStreams.get(j) == startInIndex + i) if (res != HRESULT.S_OK) return res;
seqInStreams.add(inStreams.get(j)); OutputStream seqOutStream = tmp[0];
*/ seqOutStreams.add(seqOutStream);
Vector<OutputStream> seqOutStreams = new Vector(); // CObjectVector< CMyComPtr<ISequentialOutStream> > }
int startOutIndex = bindInfo.GetCoderOutStreamIndex(mainCoderIndex); Vector<InputStream> seqInStreamsSpec = new Vector<InputStream>();
for (int i=0; i<mainCoder.NumOutStreams; i++) Vector<OutputStream> seqOutStreamsSpec = new Vector<OutputStream>();
for (int j=0; j<bindInfo.OutStreams.size(); j++) for (i = 0; i < (int)mainCoder.NumInStreams; i++)
if (bindInfo.OutStreams.get(j) == startOutIndex + i) seqInStreamsSpec.add(seqInStreams.get(i));
seqOutStreams.add(outStreams.get(j)); for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
seqOutStreamsSpec.add(seqOutStreams.get(i));
for (int i=0; i<coders.size(); i++) {
if (i == mainCoderIndex) continue; for (i = 0; i < _coders.size(); i++) {
CoderInfo coder = coders.get(i); if (i == _mainCoderIndex)
((ICompressSetOutStreamSize)coder.Coder).SetOutStreamSize(coder.OutSizePointers.Front()); continue;
} CoderInfo coder = _coders.get(i);
if (mainCoder.Coder != null) { ICompressSetOutStreamSize setOutStreamSize = null;
mainCoder.Coder.Code( try
seqInStreams.firstElement(), {
seqOutStreams.firstElement(), setOutStreamSize = (ICompressSetOutStreamSize)coder.Coder;
mainCoder.OutSizePointers.Front(),
progress); /*int res =*/ setOutStreamSize.SetOutStreamSize(coder.OutSizePointers.get(0));
} else { //if (res != HRESULT.S_OK) return res;
mainCoder.Coder2.Code( } catch (java.lang.ClassCastException e) {
seqInStreams, // nothing to do
//new Long(mainCoder.InSizePointers.Front()), }
mainCoder.NumInStreams, }
seqOutStreams, if (mainCoder.Coder != null) {
//new Long(mainCoder.OutSizePointers.Front()), /*int res =*/ mainCoder.Coder.Code(
mainCoder.NumOutStreams, seqInStreamsSpec.get(0),
progress); seqOutStreamsSpec.get(0),
} // TBD mainCoder.InSizePointers.get(0),
mainCoder.OutSizePointers.get(0),
OutputStream stream = seqOutStreams.firstElement(); progress);
if (stream != null) stream.flush(); //if (res != HRESULT.S_OK) return res;
} } else {
/*int res =*/ mainCoder.Coder2.Code(
public void close() { 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 java.util.Vector;
import SevenZip.Compression.LZ.OutWindow; import SevenZip.Compression.LZ.OutWindow;
import SevenZip.ICompressCoder2; import SevenZip.ICompressCoder2;
import SevenZip.ICompressProgressInfo; import SevenZip.ICompressProgressInfo;
import SevenZip.Common.InBuffer; import SevenZip.Common.InBuffer;
import SevenZip.HRESULT;
public class BCJ2_x86_Decoder implements ICompressCoder2 { public class BCJ2_x86_Decoder implements ICompressCoder2 {
@ -32,7 +32,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
// return ((b0 == 0x0F) && ((b1 & 0xF0) == 0x80)); // return ((b0 == 0x0F) && ((b1 & 0xF0) == 0x80));
// } // }
void CodeReal( int CodeReal(
Vector<InputStream> inStreams, Vector<InputStream> inStreams,
//Object useless1, // const UInt64 ** /* inSizes */, //Object useless1, // const UInt64 ** /* inSizes */,
int numInStreams, int numInStreams,
@ -83,7 +83,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
int b = _mainInStream.read(); int b = _mainInStream.read();
if (b == -1) { if (b == -1) {
Flush(); Flush();
return; return HRESULT.S_OK;
} }
_outStream.WriteByte(b); // System.out.println("0:"+b); _outStream.WriteByte(b); // System.out.println("0:"+b);
// if ((b != 0xE8) && (b != 0xE9) && (!IsJcc(prevByte, b))) { // if ((b != 0xE8) && (b != 0xE9) && (!IsJcc(prevByte, b))) {
@ -116,7 +116,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
src |= ((int)b0) << 8; src |= ((int)b0) << 8;
b0 = _callStream.read(); b0 = _callStream.read();
if (b0 == -1) return; // TODO: HRESULT.S_FALSE; if (b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0); src |= ((int)b0);
} else { } else {
@ -133,7 +133,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
src |= ((int)b0) << 8; src |= ((int)b0) << 8;
b0 = _jumpStream.read(); b0 = _jumpStream.read();
if(b0 == -1) return; // TODO: HRESULT.S_FALSE; if(b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0); src |= ((int)b0);
} }
@ -153,7 +153,8 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
_outStream.Flush(); _outStream.Flush();
} }
public void Code( @Override
public int Code(
Vector<InputStream> inStreams, // ISequentialInStream **inStreams, Vector<InputStream> inStreams, // ISequentialInStream **inStreams,
//Object useless_inSizes, // const UInt64 ** /* inSizes */, //Object useless_inSizes, // const UInt64 ** /* inSizes */,
int numInStreams, int numInStreams,
@ -163,7 +164,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
ICompressProgressInfo progress) throws java.io.IOException { ICompressProgressInfo progress) throws java.io.IOException {
try { try {
CodeReal(inStreams, /*useless_inSizes,*/ numInStreams, return CodeReal(inStreams, /*useless_inSizes,*/ numInStreams,
outStreams, /*useless_outSizes,*/ numOutStreams, progress); outStreams, /*useless_outSizes,*/ numOutStreams, progress);
} catch(java.io.IOException e) { } catch(java.io.IOException e) {
throw e; throw e;
@ -180,6 +181,7 @@ public class BCJ2_x86_Decoder implements ICompressCoder2 {
_outStream.ReleaseStream(); _outStream.ReleaseStream();
} }
@Override
public void close() throws java.io.IOException { public void close() throws java.io.IOException {
ReleaseStreams(); ReleaseStreams();
} }

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

Loading…
Cancel
Save