From 1f696b6fa21c10465b2b0c7df5c2fa795bd9cae9 Mon Sep 17 00:00:00 2001 From: Khaled Noaman <knoaman@apache.org> Date: Mon, 11 Jul 2005 12:33:38 +0000 Subject: [PATCH] DGXMLScanner: wrong handling of duplicate attributes git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@210108 13f79535-47bb-0310-9956-ffa450edef68 --- src/xercesc/internal/DGXMLScanner.cpp | 318 ++++++++++---------------- 1 file changed, 125 insertions(+), 193 deletions(-) diff --git a/src/xercesc/internal/DGXMLScanner.cpp b/src/xercesc/internal/DGXMLScanner.cpp index 426a8e3fd..975d86caa 100644 --- a/src/xercesc/internal/DGXMLScanner.cpp +++ b/src/xercesc/internal/DGXMLScanner.cpp @@ -1276,131 +1276,14 @@ bool DGXMLScanner::scanStartTag(bool& gotData) // See if this attribute is declared for this element. If we are // not validating of course it will not be at first, but we will // fault it into the pool (to avoid lots of redundant errors.) - XMLAttDef* attDef = ((DTDElementDecl *)elemDecl)->getAttDef ( fAttNameBuf.getRawBuffer()); XMLCh * namePtr = fAttNameBuf.getRawBuffer(); - - // Add this attribute to the attribute list that we use to - // pass them to the handler. We reuse its existing elements - // but expand it as required. - // Note that we want to this first since this will - // make a copy of the namePtr; we can then make use of - // that copy in the hashtable lookup that checks - // for duplicates. This will mean we may have to update - // the type of the XMLAttr later. - XMLAttr* curAtt; - if (attCount >= curAttListSize) - { - if (fDoNamespaces) { - curAtt = new (fMemoryManager) XMLAttr - ( - fEmptyNamespaceId - , fAttNameBuf.getRawBuffer() - , XMLUni::fgZeroLenString - , (attDef)?attDef->getType():XMLAttDef::CData - , true - , fMemoryManager - ); - } - else - { - curAtt = new (fMemoryManager) XMLAttr - ( - 0 - , fAttNameBuf.getRawBuffer() - , XMLUni::fgZeroLenString - , XMLUni::fgZeroLenString - , (attDef)?attDef->getType():XMLAttDef::CData - , true - , fMemoryManager - ); - } - fAttrList->addElement(curAtt); - } - else - { - curAtt = fAttrList->elementAt(attCount); - - if (fDoNamespaces) - { - curAtt->set - ( - fEmptyNamespaceId - , fAttNameBuf.getRawBuffer() - , XMLUni::fgZeroLenString - , (attDef)?attDef->getType():XMLAttDef::CData - ); - } - else - { - curAtt->set - ( - 0 - , fAttNameBuf.getRawBuffer() - , XMLUni::fgZeroLenString - , XMLUni::fgZeroLenString - , (attDef)?attDef->getType():XMLAttDef::CData - ); - } - curAtt->setSpecified(true); - } - // reset namePtr so it refers to newly-allocated memory - namePtr = (XMLCh *)curAtt->getName(); - - // now need to prepare for duplicate detection - if(attDef) - { - unsigned int *curCountPtr = fAttDefRegistry->get(attDef); - if(!curCountPtr) - { - curCountPtr = getNewUIntPtr(); - *curCountPtr = fElemCount; - fAttDefRegistry->put(attDef, curCountPtr); - } - else if(*curCountPtr < fElemCount) - *curCountPtr = fElemCount; - else - { - emitError - ( - XMLErrs::AttrAlreadyUsedInSTag - , attDef->getFullName() - , elemDecl->getFullName() - ); - } - } - else - { - if(!fUndeclaredAttrRegistry->containsKey(namePtr)) - fUndeclaredAttrRegistry->put((void *)namePtr, 0); - else - { - emitError - ( - XMLErrs::AttrAlreadyUsedInSTag - , namePtr - , elemDecl->getFullName() - ); - } - } - if (fValidate) - { - if (!attDef) - { - - fValidator->emitError - ( - XMLValid::AttNotDefinedForElement - , fAttNameBuf.getRawBuffer() - , qnameRawBuf - ); - } - } + XMLAttDef* attDef = ((DTDElementDecl *)elemDecl)->getAttDef(namePtr); // Skip any whitespace before the value and then scan the att // value. This will come back normalized with entity refs and // char refs expanded. fReaderMgr.skipPastSpaces(); - if (!scanAttValue(attDef, fAttNameBuf.getRawBuffer(), fAttValueBuf)) + if (!scanAttValue(attDef, namePtr, fAttValueBuf)) { static const XMLCh tmpList[] = { @@ -1433,28 +1316,118 @@ bool DGXMLScanner::scanStartTag(bool& gotData) return false; } } - // must set the newly-minted value on the XMLAttr: - curAtt->setValue(fAttValueBuf.getRawBuffer()); - // Now that its all stretched out, lets look at its type and - // determine if it has a valid value. It will output any needed - // errors, but we just keep going. We only need to do this if - // we are validating. - if (attDef) + // Add this attribute to the attribute list that we use to + // pass them to the handler. We reuse its existing elements + // but expand it as required. + // Note that we want to this first since this will + // make a copy of the namePtr; we can then make use of + // that copy in the hashtable lookup that checks + // for duplicates. This will mean we may have to update + // the type of the XMLAttr later. + XMLAttr* curAtt; + const XMLCh* attrValue = fAttValueBuf.getRawBuffer(); + + if (attCount >= curAttListSize) { + curAtt = new (fMemoryManager) XMLAttr(fMemoryManager); + fAttrList->addElement(curAtt); + } + else { + curAtt = fAttrList->elementAt(attCount); + } + + curAtt->setSpecified(true); + if (fDoNamespaces) { + curAtt->set( + fEmptyNamespaceId, namePtr, XMLUni::fgZeroLenString + , (attDef)? attDef->getType() : XMLAttDef::CData + ); + + // each attribute has the prefix:suffix="value" + const XMLCh* attPrefix = curAtt->getPrefix(); + const XMLCh* attLocalName = curAtt->getName(); + + if (attPrefix && *attPrefix) { + if (XMLString::equals(attPrefix, XMLUni::fgXMLString)) { + curAtt->setURIId(fXMLNamespaceId); + } + else if (XMLString::equals(attPrefix, XMLUni::fgXMLNSString)) { + curAtt->setURIId(fXMLNSNamespaceId); + updateNSMap(attPrefix, attLocalName, attrValue); + } + else { + fAttrNSList->addElement(curAtt); + } + } + else if (XMLString::equals(XMLUni::fgXMLNSString, attLocalName)) + { + updateNSMap(attPrefix, XMLUni::fgZeroLenString, attrValue); + } + + // NOTE: duplicate attribute check will be done, when we map + // namespaces to all attributes + } + else { + curAtt->set( + 0, namePtr, XMLUni::fgZeroLenString, XMLUni::fgZeroLenString + , (attDef)?attDef->getType():XMLAttDef::CData + ); + + // now need to prepare for duplicate detection + if (attDef) { + unsigned int *curCountPtr = fAttDefRegistry->get(attDef); + if (!curCountPtr) { + curCountPtr = getNewUIntPtr(); + *curCountPtr = fElemCount; + fAttDefRegistry->put(attDef, curCountPtr); + } + else if (*curCountPtr < fElemCount) { + *curCountPtr = fElemCount; + } + else { + emitError( + XMLErrs::AttrAlreadyUsedInSTag + , attDef->getFullName(), elemDecl->getFullName() + ); + } + } + else + { + // reset namePtr so it refers to newly-allocated memory + namePtr = (XMLCh *)curAtt->getQName(); + if (!fUndeclaredAttrRegistry->containsKey(namePtr)) { + fUndeclaredAttrRegistry->put((void *)namePtr, 0); + } + else + { + emitError( + XMLErrs::AttrAlreadyUsedInSTag + , namePtr, elemDecl->getFullName() + ); + } + } + } + + if (fValidate) { - // Let the validator pass judgement on the attribute value - if (fValidate) + if (attDef) { + // Let the validator pass judgement on the attribute value + fValidator->validateAttrValue( + attDef, fAttValueBuf.getRawBuffer(), false, elemDecl + ); + } + else { - fValidator->validateAttrValue + fValidator->emitError ( - attDef - , fAttValueBuf.getRawBuffer() - , false - , elemDecl + XMLValid::AttNotDefinedForElement + , fAttNameBuf.getRawBuffer(), qnameRawBuf ); } } + // must set the newly-minted value on the XMLAttr: + curAtt->setValue(attrValue); attCount++; // And jump back to the top of the loop @@ -2065,22 +2038,6 @@ DGXMLScanner::buildAttList(const unsigned int attCount } } - for (unsigned int i=0; i < fAttrNSList->size(); i++) { - - XMLAttr* providedAttr = fAttrNSList->elementAt(i); - - providedAttr->setURIId - ( - resolvePrefix - ( - providedAttr->getPrefix(), - ElemStack::Mode_Attribute - ) - ); - } - - fAttrNSList->removeAllElements(); - return retCount; } @@ -2354,60 +2311,37 @@ void DGXMLScanner::updateNSMap(const XMLCh* const attrPrefix void DGXMLScanner::scanAttrListforNameSpaces(RefVectorOf<XMLAttr>* theAttrList, int attCount, XMLElementDecl* elemDecl) { + // Map prefixes to uris + for (unsigned int i=0; i < fAttrNSList->size(); i++) { + XMLAttr* providedAttr = fAttrNSList->elementAt(i); + providedAttr->setURIId( + resolvePrefix(providedAttr->getPrefix(), ElemStack::Mode_Attribute) + ); + } - // - // Decide if to use hash table to do duplicate checking - // + fAttrNSList->removeAllElements(); + + // Decide if to use hash table to do duplicate checking bool toUseHashTable = false; - setAttrDupChkRegistry((unsigned int&)attCount, toUseHashTable); - // Make an initial pass through the list and find any xmlns attributes or - // schema attributes. - // When we find one, send it off to be used to update the element stack's - // namespace mappings. + setAttrDupChkRegistry((unsigned int&)attCount, toUseHashTable); for (int index = 0; index < attCount; index++) { - // each attribute has the prefix:suffix="value" - XMLAttr* curAttr = theAttrList->elementAt(index); - const XMLCh* attPrefix = curAttr->getPrefix(); - const XMLCh* attLocalName = curAttr->getName(); - - if (attPrefix && *attPrefix) - { - if (XMLString::equals(attPrefix, XMLUni::fgXMLString)) { - curAttr->setURIId(fXMLNamespaceId); - } - else if (XMLString::equals(attPrefix, XMLUni::fgXMLNSString)) { - - curAttr->setURIId(fXMLNSNamespaceId); - updateNSMap(attPrefix, attLocalName, curAttr->getValue()); - } - else { - fAttrNSList->addElement(curAttr); - } - } - else if (XMLString::equals(XMLUni::fgXMLNSString, attLocalName)) - { - updateNSMap(attPrefix, XMLUni::fgZeroLenString, curAttr->getValue()); - } - // check for duplicate namespace attributes: // by checking for qualified names with the same local part and with prefixes // which have been bound to namespace names that are identical. - XMLAttr* loopAttr; - + XMLAttr* curAttr = theAttrList->elementAt(index); if (!toUseHashTable) { + XMLAttr* loopAttr; for (int attrIndex=0; attrIndex < index; attrIndex++) { loopAttr = theAttrList->elementAt(attrIndex); if (loopAttr->getURIId() == curAttr->getURIId() && XMLString::equals(loopAttr->getName(), curAttr->getName())) { - emitError - ( - XMLErrs::AttrAlreadyUsedInSTag - , curAttr->getName() + emitError( + XMLErrs::AttrAlreadyUsedInSTag, curAttr->getName() , elemDecl->getFullName() - ); + ); } } } @@ -2415,12 +2349,10 @@ void DGXMLScanner::scanAttrListforNameSpaces(RefVectorOf<XMLAttr>* theAttrList, { if (fAttrDupChkRegistry->containsKey((void*)curAttr->getName(), curAttr->getURIId())) { - emitError - ( + emitError( XMLErrs::AttrAlreadyUsedInSTag - , curAttr->getName() - , elemDecl->getFullName() - ); + , curAttr->getName(), elemDecl->getFullName() + ); } fAttrDupChkRegistry->put((void*)curAttr->getName(), curAttr->getURIId(), curAttr); -- GitLab