-
Notifications
You must be signed in to change notification settings - Fork 9
Description
While reviewing your SNMP library, I discovered a significant memory leak related to how SNMP requests and responses are handled.
For example, when a response is added to a SNMPMessage a Varbind object is created:
Lines 1982 to 1990 in b5d3c73
| VarBind(const char *oid, BER *value = nullptr) : | |
| ArrayBER(Type::Sequence) { | |
| add(new ObjectIdentifierBER(oid)); | |
| if (value) { | |
| add(value); | |
| } else { | |
| add(new NullBER); | |
| } | |
| } |
That in part creates a ObjectIdentifierBER that it then passes to add():
Lines 1899 to 1911 in b5d3c73
| BER* add(BER *ber) { | |
| #if SNMP_VECTOR | |
| _bers.push_back(ber); | |
| _length += ber->getSize(); | |
| _count++; | |
| #else | |
| if (_count < U) { | |
| _bers[_count++] = ber; | |
| _length += ber->getSize(); | |
| } | |
| #endif | |
| return ber; | |
| } |
If vectors are not enabled (#define SNMP_VECTOR 0) and the BER array reaches its limit, the add() function silently fails to store the ObjectIdentifierBER—but the memory allocated for it is never freed. This results in a memory leak.
Here's a memory usage graph showing DRAM usage on an ESP32 when making successive bulk SNMP requests that exceed the capacity of the BER array:
Enabling vector support (#define SNMP_VECTOR 1) prevents the leak, but it removes the ability to enforce a fixed limit on the request size—something that may be important in constrained environments.
Probably this changes will need a big refactor.
