/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #include "AttributeHandlers.h" #include "ErrorHandling.h" #include "plstr.h" /* Implementation of class AttributeHandler */ AttributeHandler::AttributeHandler(Pool &pool, FileReader *_reader, ClassFileReader *_cfr, const char *_name): p(pool), name(_name), reader(_reader), cfr(_cfr) { constantPool = cfr->getConstantPool(); } int AttributeHandler::validateNameAndLength(const char *_name, Uint32 *length) { if (_name && name && PL_strcmp(name, _name) != 0) return false; /* Get the length */ if (!reader->readU4(length, 1)) verifyError(VerifyError::noClassDefFound); return true; } #define READ_INDEX(index) \ Uint16 index;\ if (!reader->readU2(&index, 1)) \ verifyError(VerifyError::noClassDefFound); /* Implementation of AttributeHandlerSourceFile */ AttributeInfoItem *AttributeHandlerSourceFile::handle(const char *_name) { Uint32 length; if (!validateNameAndLength(_name, &length)) return 0; READ_INDEX(sourceFileIndex); if (invalidAttribute(sourceFileIndex, CR_CONSTANT_UTF8)) verifyError(VerifyError::noClassDefFound); AttributeSourceFile *item = new (p) AttributeSourceFile(p, (ConstantUtf8 *) constantPool->get(sourceFileIndex)); return item; } /* Implementation of AttributeHandlerConstantValue */ AttributeInfoItem *AttributeHandlerConstantValue::handle(const char *_name) { Uint32 length; if (!validateNameAndLength(_name, &length)) return 0; READ_INDEX(constantValueIndex); if (invalidIndex(constantValueIndex)) verifyError(VerifyError::noClassDefFound); int type = constantPool->get(constantValueIndex)->getType(); /* constantValueIndex must point to a long, float, double, * integer, or string */ if (!((type > 2 && type < 7) || (type == CR_CONSTANT_STRING))) verifyError(VerifyError::noClassDefFound); AttributeConstantValue *item = new (p) AttributeConstantValue(p, const_cast (constantPool->get(constantValueIndex)), constantValueIndex); return item; } /* Implementation of AttributeHandlerCode */ AttributeInfoItem *AttributeHandlerCode::handle(const char *_name) { Uint32 length; if (!validateNameAndLength(_name, &length)) return 0; Uint16 maxStack, maxLocals; Uint32 codeLength; if (!reader->readU2(&maxStack, 1)) verifyError(VerifyError::noClassDefFound); if (!reader->readU2(&maxLocals, 1)) verifyError(VerifyError::noClassDefFound); if (!reader->readU4(&codeLength, 1)) verifyError(VerifyError::noClassDefFound); AttributeCode *code = new (p) AttributeCode(p, (Uint16) length, maxStack, maxLocals, codeLength); char *codeStr = (char *) code->getCode(); if (codeLength > 0) { if (!reader->readU1(codeStr, codeLength)) verifyError(VerifyError::noClassDefFound); } Uint16 numExceptions; if (!reader->readU2(&numExceptions, 1)) verifyError(VerifyError::noClassDefFound); if (!code->setNumExceptions(numExceptions)) verifyError(VerifyError::noClassDefFound); ExceptionItem *exceptions = const_cast (code->getExceptions()); for (int i = 0; i < numExceptions; i++) { Uint16 array[4], catchIndex; /* Read in startPc, endPc, handlerPc, catchType */ if (!reader->readU2(array, 4)) verifyError(VerifyError::noClassDefFound); if ((catchIndex = array[3]) > 0 && (invalidAttribute(catchIndex, CR_CONSTANT_CLASS))) verifyError(VerifyError::noClassDefFound); exceptions[i].startPc = array[0]; exceptions[i].endPc = array[1]; exceptions[i].handlerPc = array[2]; exceptions[i].catchType = catchIndex; } Uint16 attrCount; /* Ok, so we can have nested attributes here */ if (!reader->readU2(&attrCount, 1)) verifyError(VerifyError::noClassDefFound); if (!code->setNumAttributes(attrCount)) verifyError(VerifyError::noClassDefFound); AttributeInfoItem **attributes = (AttributeInfoItem **) code->getAttributes(); cfr->readAttributes(attributes, attrCount); return code; } /* Implementation of AttributeHandlerLineNumberTable */ AttributeInfoItem *AttributeHandlerLineNumberTable::handle(const char *_name) { Uint32 length; if (!validateNameAndLength(_name, &length)) return 0; Uint16 numEntries; if (!reader->readU2(&numEntries, 1)) verifyError(VerifyError::noClassDefFound); AttributeLineNumberTable *table = new (p) AttributeLineNumberTable(p, length); if (!table->setNumEntries(numEntries)) verifyError(VerifyError::noClassDefFound); LineNumberEntry *entries = table->getEntries(); for (int i = 0; i < numEntries; i++) { Uint16 temp[2]; if (!reader->readU2(temp, 2)) verifyError(VerifyError::noClassDefFound); entries[i].startPc = temp[0]; entries[i].lineNumber = temp[1]; } return table; } /* Implementation of AttributeHandlerLocalVariableTable */ AttributeInfoItem *AttributeHandlerLocalVariableTable::handle(const char *_name) { Uint32 length; if (!validateNameAndLength(_name, &length)) return 0; Uint16 numEntries; if (!reader->readU2(&numEntries, 1)) verifyError(VerifyError::noClassDefFound); AttributeLocalVariableTable *table = new (p) AttributeLocalVariableTable(p, length); if (!table->setNumEntries(numEntries)) verifyError(VerifyError::noClassDefFound); LocalVariableEntry *entries = table->getEntries(); for (int i = 0; i < numEntries; i++) { Uint16 temp[5]; if (!reader->readU2(temp, 5)) verifyError(VerifyError::noClassDefFound); entries[i].startPc = temp[0]; entries[i].length = temp[1]; if (invalidAttribute(temp[2], CR_CONSTANT_UTF8)) verifyError(VerifyError::noClassDefFound); entries[i].name = (ConstantUtf8 *) constantPool->get(temp[2]); if (invalidAttribute(temp[3], CR_CONSTANT_UTF8)) verifyError(VerifyError::noClassDefFound); entries[i].descriptor = (ConstantUtf8 *) constantPool->get(temp[3]); entries[i].index = temp[4]; } return table; } /* Implementation of AttributeHandlerExceptions */ AttributeInfoItem *AttributeHandlerExceptions::handle(const char *_name) { Uint32 length; if (!validateNameAndLength(_name, &length)) return 0; Uint16 numExceptions; if (!reader->readU2(&numExceptions, 1)) verifyError(VerifyError::noClassDefFound); AttributeExceptions *exception = new (p) AttributeExceptions(p, length); ConstantClass **exceptionList; if (!exception->setNumExceptions(numExceptions)) verifyError(VerifyError::noClassDefFound); exceptionList = exception->getExceptions(); for (int i = 0; i < numExceptions; i++) { Uint16 index; if (!reader->readU2(&index, 1)) verifyError(VerifyError::noClassDefFound); if (invalidAttribute(index, CR_CONSTANT_CLASS)) verifyError(VerifyError::noClassDefFound); exceptionList[i] = (ConstantClass *) constantPool->get(index); } return exception; } /* Implementation of AttributeHandlerDummy */ AttributeInfoItem *AttributeHandlerDummy::handle(const char *_name) { Uint32 length; if (!validateNameAndLength(_name, &length)) return 0; char *data = new (p) char[length]; /* Read the data */ if (!reader->readU1(data, length)) verifyError(VerifyError::noClassDefFound); AttributeInfoItem *item = new (p) AttributeInfoItem(p, name, 0, length); return item; }