Main Content

CWE Rule 375

Returning a Mutable Object to an Untrusted Caller

Since R2023a

Description

Rule Description

Sending non-cloned mutable data as a return value may result in that data being altered or deleted by the calling function.

Polyspace Implementation

The rule checker checks for Return of non-const handle to encapsulated data member.

Examples

expand all

Issue

This issue occurs when:

  • A class method returns a handle to a data member. Handles include pointers and references.

  • The method is more accessible than the data member. For instance, the method has access specifier public, but the data member is private or protected.

Risk

The access specifier determines the accessibility of a class member. For instance, a class member declared with the private access specifier cannot be accessed outside a class. Therefore, nonmember, nonfriend functions cannot modify the member.

When a class method returns a handle to a less accessible data member, the member accessibility changes. For instance, if a public method returns a pointer to a private data member, the data member is effectively not private anymore. A nonmember, nonfriend function calling the public method can use the returned pointer to view and modify the data member.

Also, if you assign the pointer to a data member of an object to another pointer, when you delete the object, the second pointer can be left dangling. The second pointer points to the part of an object that does not exist anymore.

Fix

One possible fix is to avoid returning a handle to a data member from a class method. Return a data member by value so that a copy of the member is returned. Modifying the copy does not change the data member.

If you must return a handle, use a const qualifier with the method return type so that the handle allows viewing, but not modifying, the data member.

Example — Return of Pointer to private Data Member
#include <string>
#define NUM_RECORDS 100

struct Date {
    int dd;
    int mm;
    int yyyy;
};


struct Period {
    Date startDate;
    Date endDate;
};

class DataBaseEntry {
private:
    std::string employeeName;
    Period employmentPeriod;
public:
    Period* getPeriod(void);
};

Period* DataBaseEntry::getPeriod(void) {
    return &employmentPeriod;  //Noncompliant
}


void use(Period*);
void reset(Period*);

int main() {
    DataBaseEntry dataBase[NUM_RECORDS];
    Period* tempPeriod;
    for(int i=0;i < NUM_RECORDS;i++) {
        tempPeriod = dataBase[i].getPeriod();
        use(tempPeriod);
        reset(tempPeriod);
    }
    return 0;
}

void reset(Period* aPeriod) {
       aPeriod->startDate.dd = 1;
       aPeriod->startDate.mm = 1;
       aPeriod->startDate.yyyy = 2000;
}

In this example, employmentPeriod is private to the class DataBaseEntry. It is therefore immune from modification by nonmember, nonfriend functions. However, returning a pointer to employmentPeriod breaks this encapsulation. For instance, the nonmember function reset modifies the member startDate of employmentPeriod.

Correction: Return Member by Value

One possible correction is to return the data member employmentPeriod by value instead of pointer. Modifying the return value does not change the data member because the return value is a copy of the data member.

#include <string>
#define NUM_RECORDS 100

struct Date {
    int dd;
    int mm;
    int yyyy;
};


struct Period {
    Date startDate;
    Date endDate;
};

class DataBaseEntry {
private:
    std::string employeeName;
    Period employmentPeriod;
public:
    Period getPeriod(void);
};

Period DataBaseEntry::getPeriod(void) {
    return employmentPeriod;
}


void use(Period*);
void reset(Period*);

int main() {
    DataBaseEntry dataBase[NUM_RECORDS];
    Period tempPeriodVal;
    Period* tempPeriod;
    for(int i=0;i < NUM_RECORDS;i++) {
        tempPeriodVal = dataBase[i].getPeriod();
        tempPeriod = &tempPeriodVal;
        use(tempPeriod);
        reset(tempPeriod);
    }
    return 0;
}

void reset(Period* aPeriod) {
       aPeriod->startDate.dd = 1;
       aPeriod->startDate.mm = 1;
       aPeriod->startDate.yyyy = 2000;
}

Check Information

Category: State Issues

Version History

Introduced in R2023a