Skip to content

Commit

Permalink
Fixed poss. NULL pointer dereference/double free.
Browse files Browse the repository at this point in the history
Thanks to Jinsheng Ba <[email protected]> for the report and some patches.
  • Loading branch information
michaelonken committed Oct 1, 2021
1 parent 92da003 commit a9697df
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/dcmnet/extneg.h"
#include "dcmtk/dcmnet/dcuserid.h"
#include "dcmtk/dcmnet/dicom.h"
#include "dcmtk/dcmnet/dntypes.h"
#include "dcmtk/dcmnet/dul.h"
#include "dcmtk/dcmnet/lst.h"


class DcmTransportConnection;
class DcmTransportLayer;
Expand Down Expand Up @@ -290,6 +295,9 @@ typedef struct dul_datapdu {
DUL_PRESENTATIONDATAVALUE presentationDataValue;
} DUL_DATAPDU;




#define DUL_PROTOCOL (unsigned short) 0x01

#define DUL_TYPEAPPLICATIONCONTEXT (unsigned char)0x10
Expand Down
38 changes: 38 additions & 0 deletions dcmnet/include/dcmtk/dcmnet/helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
*
* Copyright (C) 2021, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
*
* OFFIS e.V.
* R&D Division Health
* Escherweg 2
* D-26121 Oldenburg, Germany
*
*
* Module: dcmnet
*
* Author: Michael Onken
*
* Purpose: Collection of helper functions
*
*/

#ifndef DCMHET_HELPERS_H
#define DCMHET_HELPERS_H

#include "dcmtk/ofstd/ofcond.h"
#include "dcmtk/dcmnet/dulstruc.h"

struct T_ASC_Parameters;
class LST_HEAD;


void
destroyPresentationContextList(LST_HEAD ** l);

void
destroyUserInformationLists(DUL_USERINFO * userInfo);

#endif
1 change: 1 addition & 0 deletions dcmnet/libsrc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ DCMTK_ADD_LIBRARY(dcmnet
dulpres.cc
dwrap.c
extneg.cc
helpers.cc
lst.cc
scp.cc
scpcfg.cc
Expand Down
2 changes: 1 addition & 1 deletion dcmnet/libsrc/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ objs = assoc.o cond.o dcompat.o dimcancl.o dimcmd.o dimdump.o dimecho.o \
dulfsm.o dulparse.o dulpres.o dul.o lst.o extneg.o dimget.o dcmlayer.o \
dcmtrans.o dcasccfg.o dcasccff.o dccfuidh.o dccftsmp.o dccfpcmp.o \
dccfrsmp.o dccfenmp.o dccfprmp.o dfindscu.o dstorscp.o dstorscu.o \
dcuserid.o scu.o scp.o scpcfg.o scpthrd.o scppool.o dwrap.o
dcuserid.o helper.o scu.o scp.o scpcfg.o scpthrd.o scppool.o dwrap.o

library = libdcmnet.$(LIBEXT)

Expand Down
23 changes: 2 additions & 21 deletions dcmnet/libsrc/assoc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
#include "dcmtk/ofstd/ofconsol.h"
#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/dcmnet/dcmtrans.h"
#include "dcmtk/dcmnet/helpers.h"

/*
** Constant Definitions
Expand Down Expand Up @@ -336,25 +337,6 @@ ASC_createAssociationParameters(T_ASC_Parameters ** params,
return EC_Normal;
}

static void
destroyPresentationContextList(LST_HEAD ** lst)
{
DUL_PRESENTATIONCONTEXT *pc;
DUL_TRANSFERSYNTAX *ts;

if ((lst == NULL) || (*lst == NULL))
return;
while ((pc = (DUL_PRESENTATIONCONTEXT*) LST_Dequeue(lst)) != NULL) {
if (pc->proposedTransferSyntax != NULL) {
while ((ts = (DUL_TRANSFERSYNTAX*) LST_Dequeue(&pc->proposedTransferSyntax)) != NULL) {
free(ts);
}
LST_Destroy(&pc->proposedTransferSyntax);
}
free(pc);
}
LST_Destroy(lst);
}

OFCondition
ASC_destroyAssociationParameters(T_ASC_Parameters ** params)
Expand Down Expand Up @@ -1699,8 +1681,7 @@ ASC_destroyAssociation(T_ASC_Association ** association)
}

if ((*association)->params != NULL) {
cond = ASC_destroyAssociationParameters(&(*association)->params);
if (cond.bad()) return cond;
ASC_destroyAssociationParameters(&(*association)->params);
}

if ((*association)->sendPDVBuffer != NULL)
Expand Down
4 changes: 2 additions & 2 deletions dcmnet/libsrc/dcuserid.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (C) 1997-2018, OFFIS e.V.
* Copyright (C) 1997-2021, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
Expand All @@ -23,7 +23,7 @@
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/dcmnet/dcuserid.h"
#include "dcmtk/dcmnet/dul.h"
#include "dulstruc.h"
#include "dcmtk/dcmnet/dulstruc.h"

/* ************************************************************************* */
/* Implementation of class UserIdentityNegotiationSubItem */
Expand Down
2 changes: 1 addition & 1 deletion dcmnet/libsrc/dul.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ END_EXTERN_C
#include "dcmtk/ofstd/ofstd.h"

#include "dcmtk/dcmnet/dul.h"
#include "dulstruc.h"
#include "dcmtk/dcmnet/dulstruc.h"
#include "dulpriv.h"
#include "dulfsm.h"
#include "dcmtk/dcmnet/dcmtrans.h"
Expand Down
2 changes: 1 addition & 1 deletion dcmnet/libsrc/dulconst.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/lst.h"
#include "dcmtk/dcmnet/dul.h"
#include "dulstruc.h"
#include "dcmtk/dcmnet/dulstruc.h"
#include "dulpriv.h"
#include "dcmtk/ofstd/ofconsol.h"

Expand Down
2 changes: 1 addition & 1 deletion dcmnet/libsrc/dulextra.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
#include "dcmtk/dcmnet/lst.h"
#include "dcmtk/dcmnet/cond.h"
#include "dcmtk/dcmnet/dul.h"
#include "dulstruc.h"
#include "dcmtk/dcmnet/dulstruc.h"
#include "dulpriv.h"
#include "dcmtk/dcmnet/dcmtrans.h"
#include "dcmtk/dcmnet/diutil.h"
Expand Down
51 changes: 2 additions & 49 deletions dcmnet/libsrc/dulfsm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ END_EXTERN_C
#include "dcmtk/dcmnet/lst.h"
#include "dcmtk/dcmnet/cond.h"
#include "dcmtk/dcmnet/dul.h"
#include "dulstruc.h"
#include "dcmtk/dcmnet/dulstruc.h"
#include "dulpriv.h"
#include "dulfsm.h"
#include "dcmtk/ofstd/ofbmanip.h"
Expand All @@ -114,6 +114,7 @@ END_EXTERN_C
#include "dcmtk/dcmnet/dcmtrans.h"
#include "dcmtk/dcmnet/dcmlayer.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/helpers.h"
#include "dcmtk/ofstd/ofsockad.h" /* for class OFSockAddr */
#include <ctime>

Expand Down Expand Up @@ -304,9 +305,6 @@ findPresentationCtx(LST_HEAD ** lst, DUL_PRESENTATIONCONTEXTID contextID);
PRV_SCUSCPROLE *
findSCUSCPRole(LST_HEAD ** lst, char *abstractSyntax);

void destroyPresentationContextList(LST_HEAD ** l);
void destroyUserInformationLists(DUL_USERINFO * userInfo);

static volatile FSM_Event_Description Event_Table[] = {
{A_ASSOCIATE_REQ_LOCAL_USER, "A-ASSOCIATE request (local user)"},
{TRANS_CONN_CONFIRM_LOCAL_USER, "Transport conn confirmation (local)"},
Expand Down Expand Up @@ -3978,48 +3976,3 @@ findSCUSCPRole(LST_HEAD ** lst, char *abstractSyntax)
}
return NULL;
}

void
destroyPresentationContextList(LST_HEAD ** l)
{
PRV_PRESENTATIONCONTEXTITEM
* prvCtx;
DUL_SUBITEM
* subItem;

if (*l == NULL)
return;

prvCtx = (PRV_PRESENTATIONCONTEXTITEM*)LST_Dequeue(l);
while (prvCtx != NULL) {
subItem = (DUL_SUBITEM*)LST_Dequeue(&prvCtx->transferSyntaxList);
while (subItem != NULL) {
free(subItem);
subItem = (DUL_SUBITEM*)LST_Dequeue(&prvCtx->transferSyntaxList);
}
LST_Destroy(&prvCtx->transferSyntaxList);
free(prvCtx);
prvCtx = (PRV_PRESENTATIONCONTEXTITEM*)LST_Dequeue(l);
}
LST_Destroy(l);
}

void
destroyUserInformationLists(DUL_USERINFO * userInfo)
{
PRV_SCUSCPROLE
* role;

role = (PRV_SCUSCPROLE*)LST_Dequeue(&userInfo->SCUSCPRoleList);
while (role != NULL) {
free(role);
role = (PRV_SCUSCPROLE*)LST_Dequeue(&userInfo->SCUSCPRoleList);
}
LST_Destroy(&userInfo->SCUSCPRoleList);

/* extended negotiation */
delete userInfo->extNegList; userInfo->extNegList = NULL;

/* user identity negotiation */
delete userInfo->usrIdent; userInfo->usrIdent = NULL;
}
100 changes: 72 additions & 28 deletions dcmnet/libsrc/dulparse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@
#include "dcmtk/dcmnet/lst.h"
#include "dcmtk/dcmnet/dul.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dulstruc.h"
#include "dcmtk/dcmnet/dulstruc.h"
#include "dcmtk/dcmnet/helpers.h"
#include "dulpriv.h"
#include "dcmtk/ofstd/ofconsol.h"

Expand Down Expand Up @@ -142,9 +143,6 @@ parseAssociate(unsigned char *buf, unsigned long pduLength,
* context;

(void) memset(assoc, 0, sizeof(*assoc));
if ((assoc->presentationContextList = LST_Create()) == NULL) return EC_MemoryExhausted;
if ((assoc->userInfo.SCUSCPRoleList = LST_Create()) == NULL) return EC_MemoryExhausted;

// Check if the PDU actually is long enough for the fields we read
if (pduLength < 2 + 2 + 16 + 16 + 32)
return makeLengthError("associate PDU", pduLength, 2 + 2 + 16 + 16 + 32);
Expand Down Expand Up @@ -205,6 +203,8 @@ parseAssociate(unsigned char *buf, unsigned long pduLength,
<< "Called AP Title: " << assoc->calledAPTitle << OFendl
<< "Calling AP Title: " << assoc->callingAPTitle);
}
if ((assoc->presentationContextList = LST_Create()) == NULL) return EC_MemoryExhausted;
if ((assoc->userInfo.SCUSCPRoleList = LST_Create()) == NULL) return EC_MemoryExhausted;
while ((cond.good()) && (pduLength > 0))
{
type = *buf;
Expand All @@ -219,44 +219,80 @@ parseAssociate(unsigned char *buf, unsigned long pduLength,
{
buf += itemLength;
if (!OFStandard::safeSubtract(pduLength, itemLength, pduLength))
return makeUnderflowError("Application Context item", pduLength, itemLength);
DCMNET_TRACE("Successfully parsed Application Context");
{
cond = makeUnderflowError("Application Context item", pduLength, itemLength);
}
else
{
DCMNET_TRACE("Successfully parsed Application Context");
}
}
break;
case DUL_TYPEPRESENTATIONCONTEXTRQ:
case DUL_TYPEPRESENTATIONCONTEXTAC:
context = (PRV_PRESENTATIONCONTEXTITEM*)malloc(sizeof(PRV_PRESENTATIONCONTEXTITEM));
if (context == NULL) return EC_MemoryExhausted;
(void) memset(context, 0, sizeof(*context));
cond = parsePresentationContext(type, context, buf, &itemLength, pduLength);
if (cond.bad()) return cond;
buf += itemLength;
if (!OFStandard::safeSubtract(pduLength, itemLength, pduLength))
return makeUnderflowError("Presentation Context item", pduLength, itemLength);
LST_Enqueue(&assoc->presentationContextList, (LST_NODE*)context);
DCMNET_TRACE("Successfully parsed Presentation Context");
if (context != NULL)
{
(void) memset(context, 0, sizeof(*context));
cond = parsePresentationContext(type, context, buf, &itemLength, pduLength);
if (cond.bad())
{
free(context);
}
else
{
buf += itemLength;
if (!OFStandard::safeSubtract(pduLength, itemLength, pduLength))
{
cond = makeUnderflowError("Presentation Context item", pduLength, itemLength);
}
else
{
LST_Enqueue(&assoc->presentationContextList, (LST_NODE*)context);
DCMNET_TRACE("Successfully parsed Presentation Context");
}
}
}
else
{
cond = EC_MemoryExhausted;
}
break;
case DUL_TYPEUSERINFO:
// parse user info, which can contain several sub-items like User
// Identity Negotiation or SOP Class Extended Negotiation
cond = parseUserInfo(&assoc->userInfo, buf, &itemLength, assoc->type, pduLength);
if (cond.bad())
return cond;
buf += itemLength;
if (!OFStandard::safeSubtract(pduLength, itemLength, pduLength))
return makeUnderflowError("User Information item", pduLength, itemLength);
DCMNET_TRACE("Successfully parsed User Information");
if (cond.good())
{
buf += itemLength;
if (!OFStandard::safeSubtract(pduLength, itemLength, pduLength))
{
cond = makeUnderflowError("User Information item", pduLength, itemLength);
}
else
{
DCMNET_TRACE("Successfully parsed User Information");
}
}
break;
default:
cond = parseDummy(buf, &itemLength, pduLength);
if (cond.bad())
return cond;
buf += itemLength;
if (!OFStandard::safeSubtract(pduLength, itemLength, pduLength))
return makeUnderflowError("unknown item type", pduLength, itemLength);
if (cond.good())
{
buf += itemLength;
if (!OFStandard::safeSubtract(pduLength, itemLength, pduLength))
{
cond = makeUnderflowError("unknown item type", pduLength, itemLength);
}
}
break;
}
}
if (cond.bad())
{
destroyPresentationContextList(&assoc->presentationContextList);
destroyUserInformationLists(&assoc->userInfo);
}
return cond;
}

Expand Down Expand Up @@ -404,7 +440,11 @@ parsePresentationContext(unsigned char type,
subItem = (DUL_SUBITEM*)malloc(sizeof(DUL_SUBITEM));
if (subItem == NULL) return EC_MemoryExhausted;
cond = parseSubItem(subItem, buf, &length, presentationLength);
if (cond.bad()) return cond;
if (cond.bad())
{
free(subItem);
return cond;
}
LST_Enqueue(&context->transferSyntaxList, (LST_NODE*)subItem);
buf += length;
if (!OFStandard::safeSubtract(presentationLength, length, presentationLength))
Expand Down Expand Up @@ -525,7 +565,11 @@ parseUserInfo(DUL_USERINFO * userInfo,
role = (PRV_SCUSCPROLE*)malloc(sizeof(PRV_SCUSCPROLE));
if (role == NULL) return EC_MemoryExhausted;
cond = parseSCUSCPRole(role, buf, &length, userLength);
if (cond.bad()) return cond;
if (cond.bad())
{
free(role);
return cond;
}
LST_Enqueue(&userInfo->SCUSCPRoleList, (LST_NODE*)role);
buf += length;
if (!OFStandard::safeSubtract(userLength, OFstatic_cast(short unsigned int, length), userLength))
Expand Down
Loading

0 comments on commit a9697df

Please sign in to comment.