Skip to content

PVA: harden handling of protocol sizes - #3878

Open
kasemir wants to merge 2 commits into
masterfrom
pva_harden
Open

PVA: harden handling of protocol sizes#3878
kasemir wants to merge 2 commits into
masterfrom
pva_harden

Conversation

@kasemir

@kasemir kasemir commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Protocol handling was prone to memory exhaustion because of this pattern:

int count = buffer.getInteger();
Whatever[] data = new Whatever[count];
.. then read data from buffer,
.. which may actually be too small for 'count' elements

A misconfigured package can contain a huge count. This update checks the count against the remaining package size, refusing packets that are obviously too small or rather the count is obviously too large for the packet size.

Along the same lines, one could introduce an upper packet size limit similar to EPICS_CA_MAX_ARRAY_BYTES in channel access, but at this time, confirmed in a 2026-07-10 EPICS core telecon, PVA does not impose any such size limits, using all available memory.

kasemir added 2 commits July 10, 2026 13:48
Protocol handling was prone to memory exhaustion because of this pattern:
```
int count = buffer.getInteger();
Whatever[] data = new Whatever[count];
.. then read data from buffer
```

A misconfigured package can contain a huge `count`.
This update checks the `count` against the remaining package size, refusing packets that are obviously too small or rather the `count` is obviously too large for the packet size.

Along the same lines, one could introduce an upper packet size limit similar to `EPICS_CA_MAX_ARRAY_BYTES` in channel access, but at this time, confirmed in a 2026-07-10 EPICS core telecon, PVA does not impose any such size limits, using all available memory.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
D Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

💡 Need a hand with PR review? Try Gitar by Sonar!

@jacomago jacomago left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think making custom exceptions is a good suggestion by sonarlint.

{
final int size = PVASize.decodeSize(buffer);
if (size < 0 || size > buffer.remaining())
throw new Exception("Array size " + size + " with only " + buffer.remaining() + " bytes in buffer");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not throw this inside PVASize.decodeSize? Then you don't need to update every single type.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decoding the size doesn't fail. It parses the size just fine.
The calling code then checks if that size is possible within the context. If not, it throws an exception because we're stuck in a situation with no good way out other than give up and move on with the next message at a higher level. The exception text gives some potential hint to experts, showing if this is about an array size or structure size or string size or ...

@kasemir

kasemir commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

I think making custom exceptions is a good suggestion by sonarlint.

Never understood that.

Exceptions are not status codes where based on the status code you would know exactly what to do.
If a method may throw several different exceptions and you want to catch specific ones because you know exactly how to react, those are basically status codes and shouldn't be exceptions in the first place.

An exception indicates that something happened about which we can't do anything.
Exceptions are for situations where there is no good solution other than to catch and report the exception at a higher level, and move on with something else.

@jacomago

Copy link
Copy Markdown
Contributor

I think making custom exceptions is a good suggestion by sonarlint.

Never understood that.

Exceptions are not status codes where based on the status code you would know exactly what to do.
If a method may throw several different exceptions and you want to catch specific ones because you know exactly how to react, those are basically status codes and shouldn't be exceptions in the first place.

An exception indicates that something happened about which we can't do anything.
Exceptions are for situations where there is no good solution other than to catch and report the exception at a higher level, and move on with something else.

It's not just about catching custom exceptions (although I don't really understand your point about status codes, dB exception for EntityNotFoundException would makes sense there). Custom exceptions give you data structure when debugging and logging, for example you repeated the same exception message over and over in this pr. If you just make an ArrayBufferOutOFRangeException where you pass in the min, max and size you can write the message once, and format it once. Its also clear in the logs this was the type of exception that failed, I can also quickly find all places that exception is raised rather than exception I have to search for the message string.

There are many other advantages I won't bother to list them all, but using raw Exception class is a very bad code smell to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants