mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
Fix issues found when fuzzing Apache POI via Jazzer
Add some null-checks and report more meaningful exceptions This provides a bit more information than simple NullPointExceptions git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1895600 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f0e7cc0881
commit
1e9efb5562
@ -240,45 +240,52 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller {
|
||||
for (int i = 0; i < namedNodeCount; i++) {
|
||||
Attr attr = (Attr)namedNodeMap.item(0);
|
||||
|
||||
if (attr.getNamespaceURI().equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
|
||||
if (attr != null && XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attr.getNamespaceURI())) {
|
||||
// Rule M4.2
|
||||
if (attr.getValue().equals(PackageNamespaces.MARKUP_COMPATIBILITY))
|
||||
if (PackageNamespaces.MARKUP_COMPATIBILITY.equals(attr.getValue())) {
|
||||
throw new InvalidFormatException(
|
||||
"OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error.");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rule M4.3
|
||||
String elName = el.getLocalName();
|
||||
if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS))
|
||||
if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED)))
|
||||
if (PackageProperties.NAMESPACE_DCTERMS.equals(el.getNamespaceURI())) {
|
||||
if (!(KEYWORD_CREATED.equals(elName) || KEYWORD_MODIFIED.equals(elName))) {
|
||||
throw new InvalidFormatException(
|
||||
"OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: <dcterms:created> and <dcterms:modified> Consumers shall consider a document element that violates this constraint to be an error.");
|
||||
}
|
||||
}
|
||||
|
||||
// Rule M4.4
|
||||
if (el.getAttributeNodeNS(XMLConstants.XML_NS_URI, "lang") != null)
|
||||
if (el.getAttributeNodeNS(XMLConstants.XML_NS_URI, "lang") != null) {
|
||||
throw new InvalidFormatException(
|
||||
"OPC Compliance error [M4.4]: Producers shall not create a document element that contains the xml:lang attribute. Consumers shall consider a document element that violates this constraint to be an error.");
|
||||
}
|
||||
|
||||
// Rule M4.5
|
||||
if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS)) {
|
||||
if (PackageProperties.NAMESPACE_DCTERMS.equals(el.getNamespaceURI())) {
|
||||
// DCTerms namespace only use with 'created' and 'modified' elements
|
||||
if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED)))
|
||||
if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED))) {
|
||||
throw new InvalidFormatException("Namespace error : " + elName
|
||||
+ " shouldn't have the following naemspace -> "
|
||||
+ PackageProperties.NAMESPACE_DCTERMS);
|
||||
}
|
||||
|
||||
// Check for the 'xsi:type' attribute
|
||||
Attr typeAtt = el.getAttributeNodeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
|
||||
if (typeAtt == null)
|
||||
if (typeAtt == null) {
|
||||
throw new InvalidFormatException("The element '" + elName
|
||||
+ "' must have the 'xsi:type' attribute present !");
|
||||
}
|
||||
|
||||
// Check for the attribute value => 'dcterms:W3CDTF'
|
||||
if (!typeAtt.getValue().equals(el.getPrefix() + ":W3CDTF"))
|
||||
if (!typeAtt.getValue().equals(el.getPrefix() + ":W3CDTF")) {
|
||||
throw new InvalidFormatException("The element '" + elName
|
||||
+ "' must have the 'xsi:type' attribute with the value '" + el.getPrefix() + ":W3CDTF', but had '" + typeAtt.getValue() + "' !");
|
||||
+ "' must have the 'xsi:type' attribute with the value '" + el.getPrefix() + ":W3CDTF', but had '"
|
||||
+ typeAtt.getValue() + "' !");
|
||||
}
|
||||
}
|
||||
|
||||
// Check its children
|
||||
|
||||
@ -55,6 +55,9 @@ public class XDGFPageContents extends XDGFBaseContents {
|
||||
//throw new POIXMLException("Unexpected page relation: " + part);
|
||||
|
||||
XDGFMaster master = ((XDGFMasterContents)part).getMaster();
|
||||
if (master == null) {
|
||||
throw new POIXMLException("Master entry is missing in XDGFPageContents");
|
||||
}
|
||||
_masters.put(master.getID(), master);
|
||||
}
|
||||
|
||||
|
||||
@ -38,18 +38,18 @@ import com.microsoft.schemas.office.visio.x2012.main.VisioDocumentType;
|
||||
/**
|
||||
* This is your high-level starting point for working with Visio XML
|
||||
* documents (.vsdx).
|
||||
*
|
||||
*
|
||||
* Currently, only read support has been implemented, and the API is
|
||||
* not mature and is subject to change.
|
||||
*
|
||||
*
|
||||
* For more information about the visio XML format (with an XSD 1.0
|
||||
* schema), you can find documentation at
|
||||
* https://msdn.microsoft.com/en-us/library/hh645006(v=office.12).aspx
|
||||
*
|
||||
*
|
||||
* That document lacks in some areas, but you can find additional
|
||||
* documentation and an updated XSD 1.1 schema at
|
||||
* https://msdn.microsoft.com/en-us/library/office/jj684209(v=office.15).aspx
|
||||
*
|
||||
*
|
||||
* Each provides different details, but the SharePoint reference
|
||||
* has better documentation and is more useful.
|
||||
*/
|
||||
@ -101,7 +101,9 @@ public class XmlVisioDocument extends POIXMLDocument {
|
||||
_masters.onDocumentRead();
|
||||
}
|
||||
|
||||
_pages.onDocumentRead();
|
||||
if (_pages != null) {
|
||||
_pages.onDocumentRead();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,7 +117,7 @@ public class XmlVisioDocument extends POIXMLDocument {
|
||||
//
|
||||
// Useful public API goes here
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* @return pages ordered by page number
|
||||
*/
|
||||
|
||||
@ -87,7 +87,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
|
||||
private static final double DEFAULT_MARGIN_BOTTOM = 0.75;
|
||||
private static final double DEFAULT_MARGIN_LEFT = 0.7;
|
||||
private static final double DEFAULT_MARGIN_RIGHT = 0.7;
|
||||
|
||||
|
||||
//TODO make the two variable below private!
|
||||
protected CTSheet sheet;
|
||||
protected CTWorksheet worksheet;
|
||||
@ -192,6 +192,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
|
||||
}
|
||||
|
||||
private void initRows(CTWorksheet worksheetParam) {
|
||||
if (worksheetParam.getSheetData() == null || worksheetParam.getSheetData().getRowArray() == null) {
|
||||
throw new IllegalArgumentException("Had empty sheet data when initializing the sheet");
|
||||
}
|
||||
|
||||
_rows.clear();
|
||||
tables = new TreeMap<>();
|
||||
sharedFormulas = new HashMap<>();
|
||||
|
||||
@ -403,6 +403,12 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
|
||||
// Load individual sheets. The order of sheets is defined by the order
|
||||
// of CTSheet elements in the workbook
|
||||
sheets = new ArrayList<>(shIdMap.size());
|
||||
|
||||
if (this.workbook == null || this.workbook.getSheets() == null ||
|
||||
this.workbook.getSheets().getSheetArray() == null) {
|
||||
throw new POIXMLException("Cannot read a workbook without sheets");
|
||||
}
|
||||
|
||||
for (CTSheet ctSheet : this.workbook.getSheets().getSheetArray()) {
|
||||
parseSheet(shIdMap, ctSheet);
|
||||
}
|
||||
@ -671,22 +677,22 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
|
||||
clonedDg.getCTDrawing().set(dg.getCTDrawing().copy());
|
||||
|
||||
// Clone drawing relations
|
||||
XSSFDrawing drawingPatriarch = srcSheet.getDrawingPatriarch();
|
||||
if (drawingPatriarch != null) {
|
||||
List<RelationPart> srcRels = drawingPatriarch.getRelationParts();
|
||||
for (RelationPart rp : srcRels) {
|
||||
POIXMLDocumentPart r = rp.getDocumentPart();
|
||||
if (r instanceof XSSFChart) {
|
||||
// Replace chart relation part with new relationship, cloning the chart's content
|
||||
RelationPart chartPart = clonedDg.createChartRelationPart();
|
||||
XSSFChart chart = chartPart.getDocumentPart();
|
||||
chart.importContent((XSSFChart) r);
|
||||
chart.replaceReferences(clonedSheet);
|
||||
} else {
|
||||
addRelation(rp, clonedDg);
|
||||
}
|
||||
}
|
||||
}
|
||||
XSSFDrawing drawingPatriarch = srcSheet.getDrawingPatriarch();
|
||||
if (drawingPatriarch != null) {
|
||||
List<RelationPart> srcRels = drawingPatriarch.getRelationParts();
|
||||
for (RelationPart rp : srcRels) {
|
||||
POIXMLDocumentPart r = rp.getDocumentPart();
|
||||
if (r instanceof XSSFChart) {
|
||||
// Replace chart relation part with new relationship, cloning the chart's content
|
||||
RelationPart chartPart = clonedDg.createChartRelationPart();
|
||||
XSSFChart chart = chartPart.getDocumentPart();
|
||||
chart.importContent((XSSFChart) r);
|
||||
chart.replaceReferences(clonedSheet);
|
||||
} else {
|
||||
addRelation(rp, clonedDg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return clonedSheet;
|
||||
}
|
||||
@ -875,11 +881,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
|
||||
if(sheetname.length() > MAX_SENSITIVE_SHEET_NAME_LEN) {
|
||||
String trimmedSheetname = sheetname.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN);
|
||||
|
||||
// we still need to warn about the trimming as the original sheet name won't be available
|
||||
// e.g. when referenced by formulas
|
||||
LOG.atWarn().log("Sheet '{}' will be added with a trimmed name '{}' for MS Excel compliance.",
|
||||
sheetname, trimmedSheetname);
|
||||
sheetname = trimmedSheetname;
|
||||
// we still need to warn about the trimming as the original sheet name won't be available
|
||||
// e.g. when referenced by formulas
|
||||
LOG.atWarn().log("Sheet '{}' will be added with a trimmed name '{}' for MS Excel compliance.",
|
||||
sheetname, trimmedSheetname);
|
||||
sheetname = trimmedSheetname;
|
||||
}
|
||||
WorkbookUtil.validateSheetName(sheetname);
|
||||
|
||||
|
||||
@ -143,14 +143,23 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
|
||||
assert (_txmaster == null);
|
||||
_txmaster = new TxMasterStyleAtom[9];
|
||||
|
||||
if (getSlideShow() == null || getSlideShow().getDocumentRecord() == null ||
|
||||
getSlideShow().getDocumentRecord().getEnvironment() == null) {
|
||||
throw new IllegalStateException("Did not find a TxMasterStyleAtom in the current slide show");
|
||||
}
|
||||
|
||||
TxMasterStyleAtom txdoc = getSlideShow().getDocumentRecord().getEnvironment().getTxMasterStyleAtom();
|
||||
if (txdoc == null) {
|
||||
throw new IllegalStateException("Did not find a TxMasterStyleAtom in the current slide show");
|
||||
}
|
||||
|
||||
_txmaster[txdoc.getTextType()] = txdoc;
|
||||
|
||||
TxMasterStyleAtom[] txrec = ((MainMaster)getSheetContainer()).getTxMasterStyleAtoms();
|
||||
for (int i = 0; i < txrec.length; i++) {
|
||||
int txType = txrec[i].getTextType();
|
||||
for (TxMasterStyleAtom txMasterStyleAtom : txrec) {
|
||||
int txType = txMasterStyleAtom.getTextType();
|
||||
if (txType < _txmaster.length && _txmaster[txType] == null) {
|
||||
_txmaster[txType] = txrec[i];
|
||||
_txmaster[txType] = txMasterStyleAtom;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -276,7 +276,9 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh
|
||||
// Find the Document, and interesting things in it
|
||||
if (record.getRecordType() == RecordTypes.Document.typeID) {
|
||||
_documentRecord = (Document) record;
|
||||
_fonts = _documentRecord.getEnvironment().getFontCollection();
|
||||
if (_documentRecord.getEnvironment() != null) {
|
||||
_fonts = _documentRecord.getEnvironment().getFontCollection();
|
||||
}
|
||||
}
|
||||
} /*else {
|
||||
// No record at this number
|
||||
@ -414,6 +416,10 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh
|
||||
int slideId = spa.getSlideIdentifier();
|
||||
slideIdToNotes.put(slideId, idx);
|
||||
|
||||
if (notesRecord.getNotesAtom() == null) {
|
||||
throw new IllegalStateException("Could not read NotesAtom from the NotesRecord for " + idx);
|
||||
}
|
||||
|
||||
HSLFNotes hn = new HSLFNotes(notesRecord);
|
||||
hn.setSlideShow(this);
|
||||
_notes.add(hn);
|
||||
@ -436,11 +442,16 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh
|
||||
|
||||
// Ensure it really is a slide record
|
||||
if (!(r instanceof Slide)) {
|
||||
LOG.atError().log("A Slide SlideAtomSet at {} said its record was at refID {}, but that was actually a {}", box(idx),box(spa.getRefID()),r);
|
||||
LOG.atError().log("A Slide SlideAtomSet at {} said its record was at refID {}, but that was actually a {}",
|
||||
box(idx), box(spa.getRefID()), r);
|
||||
continue;
|
||||
}
|
||||
|
||||
Slide slide = (Slide)r;
|
||||
if (slide.getSlideAtom() == null) {
|
||||
LOG.atError().log("SlideAtomSet at {} at refID {} is null", box(idx), box(spa.getRefID()));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do we have a notes for this?
|
||||
HSLFNotes notes = null;
|
||||
|
||||
@ -310,10 +310,17 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
|
||||
private void initRecordOffsets(byte[] docstream, int usrOffset, NavigableMap<Integer, Record> recordMap, Map<Integer, Integer> offset2id) {
|
||||
while (usrOffset != 0) {
|
||||
UserEditAtom usr = (UserEditAtom) Record.buildRecordAtOffset(docstream, usrOffset);
|
||||
if (usr == null) {
|
||||
throw new CorruptPowerPointFileException("Powerpoint document contains no user edit atom");
|
||||
}
|
||||
|
||||
recordMap.put(usrOffset, usr);
|
||||
|
||||
int psrOffset = usr.getPersistPointersOffset();
|
||||
PersistPtrHolder ptr = (PersistPtrHolder) Record.buildRecordAtOffset(docstream, psrOffset);
|
||||
if (ptr == null) {
|
||||
throw new CorruptPowerPointFileException("Powerpoint document is missing a PersistPtrHolder at " + psrOffset);
|
||||
}
|
||||
recordMap.put(psrOffset, ptr);
|
||||
|
||||
for (Map.Entry<Integer, Integer> entry : ptr.getSlideLocationsLookup().entrySet()) {
|
||||
|
||||
@ -1322,14 +1322,18 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
|
||||
* For a given PPDrawing, grab all the TextRuns
|
||||
*/
|
||||
public static List<List<HSLFTextParagraph>> findTextParagraphs(PPDrawing ppdrawing, HSLFSheet sheet) {
|
||||
List<List<HSLFTextParagraph>> runsV = new ArrayList<>();
|
||||
for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) {
|
||||
List<HSLFTextParagraph> p = findTextParagraphs(wrapper, sheet);
|
||||
if (p != null) {
|
||||
runsV.add(p);
|
||||
}
|
||||
}
|
||||
return runsV;
|
||||
if (ppdrawing == null) {
|
||||
throw new IllegalArgumentException("Did not receive a valid drawing for sheet " + sheet._getSheetNumber());
|
||||
}
|
||||
|
||||
List<List<HSLFTextParagraph>> runsV = new ArrayList<>();
|
||||
for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) {
|
||||
List<HSLFTextParagraph> p = findTextParagraphs(wrapper, sheet);
|
||||
if (p != null) {
|
||||
runsV.add(p);
|
||||
}
|
||||
}
|
||||
return runsV;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -196,6 +196,10 @@ public class AgileDecryptor extends Decryptor {
|
||||
Cipher cipher = getCipher(skey, cipherAlgo, chainMode, iv, cipherMode);
|
||||
byte[] hashFinal;
|
||||
|
||||
if (inputKey == null) {
|
||||
throw new EncryptedDocumentException("Cannot has input without inputKey");
|
||||
}
|
||||
|
||||
try {
|
||||
inputKey = getBlock0(inputKey, getNextBlockSize(inputKey.length, blockSize));
|
||||
hashFinal = cipher.doFinal(inputKey);
|
||||
|
||||
@ -45,7 +45,7 @@ public class AgileEncryptionVerifier extends EncryptionVerifier {
|
||||
}
|
||||
|
||||
if (keyData == null) {
|
||||
throw new NullPointerException("encryptedKey not set");
|
||||
throw new IllegalArgumentException("encryptedKey not set");
|
||||
}
|
||||
|
||||
setCipherAlgorithm(keyData.getCipherAlgorithm());
|
||||
@ -64,14 +64,17 @@ public class AgileEncryptionVerifier extends EncryptionVerifier {
|
||||
keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
|
||||
}
|
||||
|
||||
setSpinCount(keyData.getSpinCount());
|
||||
Integer spinCount = keyData.getSpinCount();
|
||||
if (spinCount != null) {
|
||||
setSpinCount(spinCount);
|
||||
}
|
||||
setEncryptedVerifier(keyData.getEncryptedVerifierHashInput());
|
||||
setSalt(keyData.getSaltValue());
|
||||
setEncryptedKey(keyData.getEncryptedKeyValue());
|
||||
setEncryptedVerifierHash(keyData.getEncryptedVerifierHashValue());
|
||||
|
||||
int saltSize = keyData.getSaltSize();
|
||||
if (saltSize != getSalt().length) {
|
||||
Integer saltSize = keyData.getSaltSize();
|
||||
if (saltSize == null || saltSize != getSalt().length) {
|
||||
throw new EncryptedDocumentException("Invalid salt size");
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ import org.apache.poi.poifs.property.RootProperty;
|
||||
import org.apache.poi.poifs.storage.BATBlock;
|
||||
import org.apache.poi.poifs.storage.BATBlock.BATBlockAndIndex;
|
||||
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||
import org.apache.poi.util.RecordFormatException;
|
||||
|
||||
/**
|
||||
* This class handles the MiniStream (small block store)
|
||||
@ -43,6 +44,9 @@ public class POIFSMiniStore extends BlockStore {
|
||||
|
||||
POIFSMiniStore(POIFSFileSystem filesystem, RootProperty root,
|
||||
List<BATBlock> sbats, HeaderBlock header) {
|
||||
if (root == null) {
|
||||
throw new RecordFormatException("Invalid argument to POIFSMiniStore: root is null");
|
||||
}
|
||||
this._filesystem = filesystem;
|
||||
this._sbat_blocks = sbats;
|
||||
this._header = header;
|
||||
|
||||
@ -105,7 +105,9 @@ public final class PropertyTable implements BATManaged {
|
||||
PropertyFactory.convertToProperties(data, _properties);
|
||||
}
|
||||
|
||||
populatePropertyTree( (DirectoryProperty)_properties.get(0));
|
||||
if (_properties.get(0) != null) {
|
||||
populatePropertyTree((DirectoryProperty) _properties.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user