Skip to content

Compiler errors, and potential problems #83

Description

@hb020

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:

  1. let it be
  2. 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.
  3. 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:

Image

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:

Image

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions