TL;DR
There are a certain number of issues with the AR488 code that can cause crashes: array size too small and trying to read a string from a NULL pointer. They are mostly (only?) in the prologix interpreter.
These issues also prevent the use of the code in other environments. The code will crash when compiled with picolibc (like for example via Zephyr). Picolibc has no protection against NULL pointer use, unlike the Arduino libc.
There are 3 ways we can go about this:
- let it be
- I repair that. I will make sure that there are no structural changes, all functions still have the same signature, and will be at the same place. There will just be a bit more protection inside of them. It won't be much effort for me now.
- you repair that.
Tell me how you want to take that on.
Problem 1
Level: serious, can provoke problems.
My compiler complains about the size of an array:
/...../AR488_ComPorts.cpp: In function 'void printHexAscii(uint8_t)':
/...../AR488_ComPorts.cpp:128:12: error: 'sprintf' output 8 bytes into a destination of size 6
128 | sprintf(x,"%c [%02X]\n", byteval, byteval);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proposition:
Problem 2.
Level: Serious
fndl_h uses uint8_t addrList[15] = {0}; But it can be filled up to 32 elements (not 31!).
So: please use 32, and adapt some more code, from
void fndl_h(char *params) {
char *param;
uint16_t addrval = 0;
uint8_t addrList[15] = {0};
.....
// Initialise arrays
for (int i = 0; i < 15; i++) {
addrList[i] = 0;
}
.....
if (j==0) {
// Read address parameters into array
while (j < 15) {
to
void fndl_h(char *params) {
char *param;
uint16_t addrval = 0;
uint8_t addrList[32] = {0};
.....
// Initialise arrays
for (int i = 0; i < (int)sizeof(addrList); i++) {
addrList[i] = 0;
}
.....
if (j==0) {
// Read address parameters into array
while (j < (int)sizeof(addrList)) {
Problem 3.
Level: serious. Partly depends how you look at it, how you use it, partly crashing
When compiled outside of Arduino, and therefore using others libc implementations, like picolibc, one encounters many serious problems. These are all due to the fact that the existing AR488 code does not always check for NULL pointers. Picolibc does NOT check for parameter validity in functions like strncasecmp or strtol or strlen (see here for example.).
But the code changes that would be needed in AR488 for that are everywhere. Some functions are protected, some are not, like send_h(), xdiag_h(), fndl_h().
And there are cases where the protection of strlen would not matter, since it would crash also on arduino:
Try this with param NULL: if (param[strlen(param)-1] == '?') isQuery = true; (in send_h())
and isNumber(NULL) = true. Not great.
Problem 4.
Level: minor.
My compiler complains about an unused parameter.
/...../AR488_main.cpp: In function 'void default_h(char*)':
/...../AR488_main.cpp:2214:22: error: unused parameter 'params' [-Werror=unused-parameter]
2108
| void default_h(char *params) {
| ~~~~~~^~~~~~
Proposition:
Problem 5.
Level: don't know yet.
see the following code snippet from AR488.ino, inside void id_h(char *params):
if (strncasecmp(keyword, "name", 4)==0) {
dataPort.println(gpibBus.cfg.sname);
return;
} void addr_h(char *params);
if (strncasecmp(keyword, "serial", 6)==0) {
unsigned long int serialnum = gpibBus.cfg.serial;
No idea what that void addr_h(char *params); is doing there. Probably a copy/paste that went rogue.
Problem 6.
Level: buggy when outside of Arduino
GPIB_CFG_SIZE is off when compiled outside of Arduino: it is too small, thereby missing the last bytes in the struct.
It is likely that my compiler does not want to pack the struct at byte boundaries, making it bigger than how it is under Arduino.
When adding
static_assert(sizeof(gpibBus.cfg) == GPIB_CFG_SIZE, "The size of the GPIB configuration is incorrect. Please check AR488_GPIBbus.h, and adjust GPIB_CFG_SIZE accordingly.");
it becomes visible. No idea if the Arduino compiler supports that though.
There are other ways of coding it, avoiding the need for GPIB_CFG_SIZE: one can eliminate db and just pass sizeof() to the read/write functions.
TL;DR
There are a certain number of issues with the AR488 code that can cause crashes: array size too small and trying to read a string from a NULL pointer. They are mostly (only?) in the prologix interpreter.
These issues also prevent the use of the code in other environments. The code will crash when compiled with picolibc (like for example via Zephyr). Picolibc has no protection against NULL pointer use, unlike the Arduino libc.
There are 3 ways we can go about this:
Tell me how you want to take that on.
Problem 1
Level: serious, can provoke problems.
My compiler complains about the size of an array:
Proposition:
Problem 2.
Level: Serious
fndl_husesuint8_t addrList[15] = {0};But it can be filled up to 32 elements (not 31!).So: please use 32, and adapt some more code, from
to
Problem 3.
Level: serious. Partly depends how you look at it, how you use it, partly crashing
When compiled outside of Arduino, and therefore using others libc implementations, like picolibc, one encounters many serious problems. These are all due to the fact that the existing AR488 code does not always check for NULL pointers. Picolibc does NOT check for parameter validity in functions like
strncasecmporstrtolorstrlen(see here for example.).But the code changes that would be needed in AR488 for that are everywhere. Some functions are protected, some are not, like
send_h(),xdiag_h(),fndl_h().And there are cases where the protection of
strlenwould not matter, since it would crash also on arduino:Try this with
paramNULL:if (param[strlen(param)-1] == '?') isQuery = true;(insend_h())and
isNumber(NULL)= true. Not great.Problem 4.
Level: minor.
My compiler complains about an unused parameter.
Proposition:
Problem 5.
Level: don't know yet.
see the following code snippet from
AR488.ino, insidevoid id_h(char *params):No idea what that
void addr_h(char *params);is doing there. Probably a copy/paste that went rogue.Problem 6.
Level: buggy when outside of Arduino
GPIB_CFG_SIZEis off when compiled outside of Arduino: it is too small, thereby missing the last bytes in the struct.It is likely that my compiler does not want to pack the struct at byte boundaries, making it bigger than how it is under Arduino.
When adding
it becomes visible. No idea if the Arduino compiler supports that though.
There are other ways of coding it, avoiding the need for
GPIB_CFG_SIZE: one can eliminatedband just passsizeof()to the read/write functions.