From da8c801a4d08baeee8007276c1f73f11c4a890ce Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Thu, 31 Dec 2020 11:53:21 +0100 Subject: Fix cases where classes inside inline namespaces could lead to crashes --- src/classdef.cpp | 54 ++++---- src/doxygen.cpp | 367 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 231 insertions(+), 190 deletions(-) diff --git a/src/classdef.cpp b/src/classdef.cpp index 0653203..4492f3e 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -3185,11 +3185,13 @@ void ClassDefImpl::addTypeConstraint(const QCString &typeConstraint,const QCStri getDefColumn(), typeConstraint, ClassDef::Class)))); - - cd->setUsedOnly(TRUE); - cd->setLanguage(getLanguage()); - //printf("Adding undocumented constraint '%s' to class %s on type %s\n", - // typeConstraint.data(),name().data(),type.data()); + if (cd) + { + cd->setUsedOnly(TRUE); + cd->setLanguage(getLanguage()); + //printf("Adding undocumented constraint '%s' to class %s on type %s\n", + // typeConstraint.data(),name().data(),type.data()); + } } if (cd) { @@ -3997,34 +3999,38 @@ ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName, QCString tcname = removeRedundantWhiteSpace(localName()+templSpec); Debug::print(Debug::Classes,0," New template instance class '%s''%s' inside '%s' hidden=%d\n",qPrint(name()),qPrint(templSpec),qPrint(name()),isHidden()); - templateClass = toClassDefMutable(Doxygen::classLinkedMap->find(tcname)); - if (templateClass==0) + ClassDef *foundCd = Doxygen::classLinkedMap->find(tcname); + if (foundCd) + { + return foundCd; + } + templateClass = + toClassDefMutable( + Doxygen::classLinkedMap->add(tcname, + std::unique_ptr( + new ClassDefImpl(fileName,startLine,startColumn,tcname,ClassDef::Class)))); + templateClass->setTemplateMaster(this); + templateClass->setOuterScope(getOuterScope()); + templateClass->setHidden(isHidden()); + m_impl->templateInstances->insert(templSpec,templateClass); + + // also add nested classes + for (const auto &innerCd : m_impl->innerClasses) { - templateClass = + QCString innerName = tcname+"::"+innerCd->localName(); + ClassDefMutable *innerClass = toClassDefMutable( - Doxygen::classLinkedMap->add(tcname, + Doxygen::classLinkedMap->add(innerName, std::unique_ptr( - new ClassDefImpl(fileName,startLine,startColumn,tcname,ClassDef::Class)))); - templateClass->setTemplateMaster(this); - templateClass->setOuterScope(getOuterScope()); - templateClass->setHidden(isHidden()); - m_impl->templateInstances->insert(templSpec,templateClass); - - // also add nested classes - for (const auto &innerCd : m_impl->innerClasses) + new ClassDefImpl(fileName,startLine,startColumn,innerName,ClassDef::Class)))); + if (innerClass) { - QCString innerName = tcname+"::"+innerCd->localName(); - ClassDefMutable *innerClass = - toClassDefMutable( - Doxygen::classLinkedMap->add(innerName, - std::unique_ptr( - new ClassDefImpl(fileName,startLine,startColumn,innerName,ClassDef::Class)))); templateClass->addInnerCompound(innerClass); innerClass->setOuterScope(templateClass); innerClass->setHidden(isHidden()); } - freshInstance=TRUE; } + freshInstance=TRUE; } return templateClass; } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 71b2a6b..642ea0d 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -1089,39 +1089,44 @@ static void addClassToContext(const Entry *root) std::unique_ptr( createClassDef(tagInfo?tagName:root->fileName,root->startLine,root->startColumn, fullName,sec,tagName,refFileName,TRUE,root->spec&Entry::Enum) ))); - Debug::print(Debug::Classes,0," New class '%s' (sec=0x%08x)! #tArgLists=%d tagInfo=%p hidden=%d artificial=%d\n", - qPrint(fullName),sec,root->tArgLists.size(), tagInfo,root->hidden,root->artificial); - cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition - cd->setBriefDescription(root->brief,root->briefFile,root->briefLine); - cd->setLanguage(root->lang); - cd->setId(root->id); - cd->setHidden(root->hidden); - cd->setArtificial(root->artificial); - cd->setClassSpecifier(root->spec); - cd->setTypeConstraints(root->typeConstr); - //printf("new ClassDef %s tempArgList=%p specScope=%s\n",fullName.data(),root->tArgList,root->scopeSpec.data()); - - //printf("class %s template args=%s\n",fullName.data(), - // tArgList ? tempArgListToString(tArgList,root->lang).data() : ""); - if (tArgList) + if (cd) { - cd->setTemplateArguments(*tArgList); - } - cd->setProtection(root->protection); - cd->setIsStatic(root->stat); - - // file definition containing the class cd - cd->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); - cd->setBodyDef(fd); - - cd->setMetaData(root->metaData); + Debug::print(Debug::Classes,0," New class '%s' (sec=0x%08x)! #tArgLists=%d tagInfo=%p hidden=%d artificial=%d\n", + qPrint(fullName),sec,root->tArgLists.size(), tagInfo,root->hidden,root->artificial); + cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition + cd->setBriefDescription(root->brief,root->briefFile,root->briefLine); + cd->setLanguage(root->lang); + cd->setId(root->id); + cd->setHidden(root->hidden); + cd->setArtificial(root->artificial); + cd->setClassSpecifier(root->spec); + cd->setTypeConstraints(root->typeConstr); + //printf("new ClassDef %s tempArgList=%p specScope=%s\n",fullName.data(),root->tArgList,root->scopeSpec.data()); + + //printf("class %s template args=%s\n",fullName.data(), + // tArgList ? tempArgListToString(tArgList,root->lang).data() : ""); + if (tArgList) + { + cd->setTemplateArguments(*tArgList); + } + cd->setProtection(root->protection); + cd->setIsStatic(root->stat); - // see if the class is found inside a namespace - //bool found=addNamespace(root,cd); + // file definition containing the class cd + cd->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); + cd->setBodyDef(fd); - cd->insertUsedFile(fd); + cd->setMetaData(root->metaData); + // see if the class is found inside a namespace + //bool found=addNamespace(root,cd); + cd->insertUsedFile(fd); + } + else + { + Debug::print(Debug::Classes,0," Not added class '%s', already exists as alias\n", qPrint(fullName)); + } } cd->addSectionsToDefinition(root->anchors); @@ -1333,64 +1338,67 @@ static ClassDefMutable *createTagLessInstance(const ClassDef *rootCd,const Class templ->getDefColumn(), fullName, templ->compoundType())))); - cd->setDocumentation(templ->documentation(),templ->docFile(),templ->docLine()); // copy docs to definition - cd->setBriefDescription(templ->briefDescription(),templ->briefFile(),templ->briefLine()); - cd->setLanguage(templ->getLanguage()); - cd->setBodySegment(templ->getDefLine(),templ->getStartBodyLine(),templ->getEndBodyLine()); - cd->setBodyDef(templ->getBodyDef()); - - cd->setOuterScope(rootCd->getOuterScope()); - if (rootCd->getOuterScope()!=Doxygen::globalScope) + if (cd) { - DefinitionMutable *outerScope = toDefinitionMutable(rootCd->getOuterScope()); - if (outerScope) + cd->setDocumentation(templ->documentation(),templ->docFile(),templ->docLine()); // copy docs to definition + cd->setBriefDescription(templ->briefDescription(),templ->briefFile(),templ->briefLine()); + cd->setLanguage(templ->getLanguage()); + cd->setBodySegment(templ->getDefLine(),templ->getStartBodyLine(),templ->getEndBodyLine()); + cd->setBodyDef(templ->getBodyDef()); + + cd->setOuterScope(rootCd->getOuterScope()); + if (rootCd->getOuterScope()!=Doxygen::globalScope) { - outerScope->addInnerCompound(cd); + DefinitionMutable *outerScope = toDefinitionMutable(rootCd->getOuterScope()); + if (outerScope) + { + outerScope->addInnerCompound(cd); + } } - } - FileDef *fd = templ->getFileDef(); - if (fd) - { - cd->setFileDef(fd); - fd->insertClass(cd); - } - GroupList *groups = rootCd->partOfGroups(); - if ( groups!=0 ) - { - GroupListIterator gli(*groups); - GroupDef *gd; - for (gli.toFirst();(gd=gli.current());++gli) + FileDef *fd = templ->getFileDef(); + if (fd) { - cd->makePartOfGroup(gd); - gd->addClass(cd); + cd->setFileDef(fd); + fd->insertClass(cd); + } + GroupList *groups = rootCd->partOfGroups(); + if ( groups!=0 ) + { + GroupListIterator gli(*groups); + GroupDef *gd; + for (gli.toFirst();(gd=gli.current());++gli) + { + cd->makePartOfGroup(gd); + gd->addClass(cd); + } } - } - MemberList *ml = templ->getMemberList(MemberListType_pubAttribs); - if (ml) - { - MemberListIterator li(*ml); - MemberDef *md; - for (li.toFirst();(md=li.current());++li) + MemberList *ml = templ->getMemberList(MemberListType_pubAttribs); + if (ml) { - //printf(" Member %s type=%s\n",md->name().data(),md->typeString()); - MemberDefMutable *imd = createMemberDef(md->getDefFileName(),md->getDefLine(),md->getDefColumn(), - md->typeString(),md->name(),md->argsString(),md->excpString(), - md->protection(),md->virtualness(),md->isStatic(),Member, - md->memberType(), - ArgumentList(),ArgumentList(),""); - imd->setMemberClass(cd); - imd->setDocumentation(md->documentation(),md->docFile(),md->docLine()); - imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine()); - imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); - imd->setMemberSpecifiers(md->getMemberSpecifiers()); - imd->setMemberGroupId(md->getMemberGroupId()); - imd->setInitializer(md->initializer()); - imd->setMaxInitLines(md->initializerLines()); - imd->setBitfields(md->bitfieldString()); - imd->setLanguage(md->getLanguage()); - cd->insertMember(imd); + MemberListIterator li(*ml); + MemberDef *md; + for (li.toFirst();(md=li.current());++li) + { + //printf(" Member %s type=%s\n",md->name().data(),md->typeString()); + MemberDefMutable *imd = createMemberDef(md->getDefFileName(),md->getDefLine(),md->getDefColumn(), + md->typeString(),md->name(),md->argsString(),md->excpString(), + md->protection(),md->virtualness(),md->isStatic(),Member, + md->memberType(), + ArgumentList(),ArgumentList(),""); + imd->setMemberClass(cd); + imd->setDocumentation(md->documentation(),md->docFile(),md->docLine()); + imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine()); + imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); + imd->setMemberSpecifiers(md->getMemberSpecifiers()); + imd->setMemberGroupId(md->getMemberGroupId()); + imd->setInitializer(md->initializer()); + imd->setMaxInitLines(md->initializerLines()); + imd->setBitfields(md->bitfieldString()); + imd->setLanguage(md->getLanguage()); + cd->insertMember(imd); + } } } return cd; @@ -1435,29 +1443,32 @@ static void processTagLessClasses(const ClassDef *rootCd, if (!prefix.isEmpty()) name.prepend(prefix+"."); //printf(" found %s for class %s\n",name.data(),cd->name().data()); ClassDefMutable *ncd = createTagLessInstance(rootCd,icd,name); - processTagLessClasses(rootCd,icd,ncd,name,count+1); - //printf(" addTagged %s to %s\n",ncd->name().data(),tagParentCd->name().data()); - ncd->setTagLessReference(icd); - - // replace tag-less type for generated/original member - // by newly created class name. - // note the difference between changing cd and tagParentCd. - // for the initial call this is the same pointer, but for - // recursive calls cd is the original tag-less struct (of which - // there is only one instance) and tagParentCd is the newly - // generated tagged struct of which there can be multiple instances! - MemberList *pml = tagParentCd->getMemberList(MemberListType_pubAttribs); - if (pml) + if (ncd) { - MemberListIterator pli(*pml); - MemberDef *pmd; - for (pli.toFirst();(pmd=pli.current());++pli) + processTagLessClasses(rootCd,icd,ncd,name,count+1); + //printf(" addTagged %s to %s\n",ncd->name().data(),tagParentCd->name().data()); + ncd->setTagLessReference(icd); + + // replace tag-less type for generated/original member + // by newly created class name. + // note the difference between changing cd and tagParentCd. + // for the initial call this is the same pointer, but for + // recursive calls cd is the original tag-less struct (of which + // there is only one instance) and tagParentCd is the newly + // generated tagged struct of which there can be multiple instances! + MemberList *pml = tagParentCd->getMemberList(MemberListType_pubAttribs); + if (pml) { - MemberDefMutable *pmdm = toMemberDefMutable(pmd); - if (pmdm && pmd->name()==md->name()) + MemberListIterator pli(*pml); + MemberDef *pmd; + for (pli.toFirst();(pmd=pli.current());++pli) { - pmdm->setAccessorType(ncd,substitute(pmd->typeString(),icd->name(),ncd->name())); - //pmd->setType(substitute(pmd->typeString(),icd->name(),ncd->name())); + MemberDefMutable *pmdm = toMemberDefMutable(pmd); + if (pmdm && pmd->name()==md->name()) + { + pmdm->setAccessorType(ncd,substitute(pmd->typeString(),icd->name(),ncd->name())); + //pmd->setType(substitute(pmd->typeString(),icd->name(),ncd->name())); + } } } } @@ -1783,38 +1794,41 @@ static void findUsingDirectives(const Entry *root) Doxygen::namespaceLinkedMap->add(name, std::unique_ptr( createNamespaceDef(root->fileName,root->startLine,root->startColumn,name)))); - nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition - nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); - nd->addSectionsToDefinition(root->anchors); - //printf("** Adding namespace %s hidden=%d\n",name.data(),root->hidden); - nd->setHidden(root->hidden); - nd->setArtificial(TRUE); - nd->setLanguage(root->lang); - nd->setId(root->id); - nd->setMetaData(root->metaData); - nd->setInline((root->spec&Entry::Inline)!=0); - - //QListIterator gli(*root->groups); - //Grouping *g; - //for (;(g=gli.current());++gli) - for (const Grouping &g : root->groups) + if (nd) { - GroupDef *gd=0; - if (!g.groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g.groupname))) - gd->addNamespace(nd); - } + nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition + nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); + nd->addSectionsToDefinition(root->anchors); + //printf("** Adding namespace %s hidden=%d\n",name.data(),root->hidden); + nd->setHidden(root->hidden); + nd->setArtificial(TRUE); + nd->setLanguage(root->lang); + nd->setId(root->id); + nd->setMetaData(root->metaData); + nd->setInline((root->spec&Entry::Inline)!=0); - // insert the namespace in the file definition - if (fd) - { - fd->insertNamespace(nd); - fd->addUsingDirective(nd); - } + //QListIterator gli(*root->groups); + //Grouping *g; + //for (;(g=gli.current());++gli) + for (const Grouping &g : root->groups) + { + GroupDef *gd=0; + if (!g.groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g.groupname))) + gd->addNamespace(nd); + } - // the empty string test is needed for extract all case - nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); - nd->insertUsedFile(fd); - nd->setRefItems(root->sli); + // insert the namespace in the file definition + if (fd) + { + fd->insertNamespace(nd); + fd->addUsingDirective(nd); + } + + // the empty string test is needed for extract all case + nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); + nd->insertUsedFile(fd); + nd->setRefItems(root->sli); + } } } } @@ -1900,8 +1914,11 @@ static void findUsingDeclarations(const Entry *root) Doxygen::hiddenClassLinkedMap->add(name, std::unique_ptr( createClassDef( "",1,1, name, ClassDef::Class)))); - usingCd->setArtificial(TRUE); - usingCd->setLanguage(root->lang); + if (usingCd) + { + usingCd->setArtificial(TRUE); + usingCd->setLanguage(root->lang); + } } else { @@ -3988,10 +4005,13 @@ static void findUsedClassesForClass(const Entry *root, masterCd->getDefColumn(), usedName, ClassDef::Class)))); - //printf("making %s a template argument!!!\n",usedCd->name().data()); - usedCd->makeTemplateArgument(); - usedCd->setUsedOnly(TRUE); - usedCd->setLanguage(masterCd->getLanguage()); + if (usedCd) + { + //printf("making %s a template argument!!!\n",usedCd->name().data()); + usedCd->makeTemplateArgument(); + usedCd->setUsedOnly(TRUE); + usedCd->setLanguage(masterCd->getLanguage()); + } } if (isArtificial) usedCd->setArtificial(TRUE); Debug::print(Debug::Classes,0," Adding used class '%s' (1)\n", qPrint(usedCd->name())); @@ -4037,8 +4057,11 @@ static void findUsedClassesForClass(const Entry *root, masterCd->getDefFileName(),masterCd->getDefLine(), masterCd->getDefColumn(), type,ClassDef::Class)))); - usedCd->setUsedOnly(TRUE); - usedCd->setLanguage(masterCd->getLanguage()); + if (usedCd) + { + usedCd->setUsedOnly(TRUE); + usedCd->setLanguage(masterCd->getLanguage()); + } } if (usedCd) { @@ -4533,8 +4556,8 @@ static bool findClassRelation( baseClass=0; if (isATemplateArgument) { - baseClass=toClassDefMutable(Doxygen::hiddenClassLinkedMap->find(baseClassName)); - if (baseClass==0) + baseClass = toClassDefMutable(Doxygen::hiddenClassLinkedMap->find(baseClassName)); + if (baseClass==0) // not found (or alias) { baseClass= toClassDefMutable( Doxygen::hiddenClassLinkedMap->add(baseClassName, @@ -4542,14 +4565,16 @@ static bool findClassRelation( createClassDef(root->fileName,root->startLine,root->startColumn, baseClassName, ClassDef::Class)))); - if (isArtificial) baseClass->setArtificial(TRUE); - baseClass->setLanguage(root->lang); - + if (baseClass) // really added (not alias) + { + if (isArtificial) baseClass->setArtificial(TRUE); + baseClass->setLanguage(root->lang); + } } } else { - baseClass=toClassDefMutable(Doxygen::classLinkedMap->find(baseClassName)); + baseClass = toClassDefMutable(Doxygen::classLinkedMap->find(baseClassName)); //printf("*** classDDict->find(%s)=%p biName=%s templSpec=%s\n", // baseClassName.data(),baseClass,biName.data(),templSpec.data()); if (baseClass==0) @@ -4560,41 +4585,51 @@ static bool findClassRelation( createClassDef(root->fileName,root->startLine,root->startColumn, baseClassName, ClassDef::Class)))); - if (isArtificial) baseClass->setArtificial(TRUE); - baseClass->setLanguage(root->lang); - si = baseClassName.findRev("::"); - if (si!=-1) // class is nested + if (baseClass) { - Definition *sd = findScopeFromQualifiedName(Doxygen::globalScope,baseClassName.left(si),0,root->tagInfo()); - if (sd==0 || sd==Doxygen::globalScope) // outer scope not found + if (isArtificial) baseClass->setArtificial(TRUE); + baseClass->setLanguage(root->lang); + si = baseClassName.findRev("::"); + if (si!=-1) // class is nested { - baseClass->setArtificial(TRUE); // see bug678139 + Definition *sd = findScopeFromQualifiedName(Doxygen::globalScope,baseClassName.left(si),0,root->tagInfo()); + if (sd==0 || sd==Doxygen::globalScope) // outer scope not found + { + baseClass->setArtificial(TRUE); // see bug678139 + } } } } } - if (biName.right(2)=="-p") + if (baseClass) { - biName="<"+biName.left(biName.length()-2)+">"; - } - // add base class to this class - cd->insertBaseClass(baseClass,biName,bi->prot,bi->virt,templSpec); - // add this class as super class to the base class - baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); - // the undocumented base was found in this file - baseClass->insertUsedFile(root->fileDef()); - - Definition *scope = buildScopeFromQualifiedName(baseClass->name(),root->lang,0); - if (scope!=baseClass) - { - baseClass->setOuterScope(scope); - } + if (biName.right(2)=="-p") + { + biName="<"+biName.left(biName.length()-2)+">"; + } + // add base class to this class + cd->insertBaseClass(baseClass,biName,bi->prot,bi->virt,templSpec); + // add this class as super class to the base class + baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); + // the undocumented base was found in this file + baseClass->insertUsedFile(root->fileDef()); + + Definition *scope = buildScopeFromQualifiedName(baseClass->name(),root->lang,0); + if (scope!=baseClass) + { + baseClass->setOuterScope(scope); + } - if (baseClassName.right(2)=="-p") + if (baseClassName.right(2)=="-p") + { + baseClass->setCompoundType(ClassDef::Protocol); + } + return TRUE; + } + else { - baseClass->setCompoundType(ClassDef::Protocol); + Debug::print(Debug::Classes,0," Base class '%s' not created (alias?)\n",qPrint(biName)); } - return TRUE; } else { -- cgit v0.12