Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

le_read16, be_read16 can return incorrect values #894

Open
tsteven4 opened this issue Jul 23, 2022 · 2 comments
Open

le_read16, be_read16 can return incorrect values #894

tsteven4 opened this issue Jul 23, 2022 · 2 comments

Comments

@tsteven4
Copy link
Collaborator

tsteven4 commented Jul 23, 2022

On a twos complement little endian machine with 4 byte integers the following code

int16_t number{-30964};
qDebug() << le_read16(&number);

results in a positive number being returned.
34572

-30964 as a two's complement 16 bit integer is 0x870C.
34572 as a 32 bit signed integer is 0x0000870C.
-30964 as a two's complement 32 bit integer is 0xFFFF870C.

It seems like navilink/sbp, sbn and skytraq count on this error.

Note 4 byte integers are very common these days (e.g. LLP64, LP64).

The endian routines in util.cc can be implemented with templates from QtEndian.

@robertlipe
Copy link
Collaborator

robertlipe commented Jul 23, 2022 via email

@tsteven4
Copy link
Collaborator Author

tsteven4 commented Jul 24, 2022

The lack of sign extension in [bl]e_read16, with >2 byte ints, is the issue. Historically the "signed" versions [bl]e_read(16|32) are much older than unsigned versions [bl]e_readu(16|32) (~ dc2158394 in 2002 vs. ~ a1ed48e1e in 2008). Today, the problem is that all the binary formats were developed without sign extension in the "signed" versions, and in many cases relied on that fact. In many cases they should have used [bl]e_readu16 instead of [bl]e_read16, but either because of history or a format uncertainty they didn't. After the fact it is difficult to decide if each use should be signed or unsigned.

If we change le_read16 (and the rest similarly) to

signed int
le_read16(const void* ptr)
{
  return qFromLittleEndian<qint16>(ptr);
}

which does the sign extension, then we have many test case failures.

std:endian is c++20, and std::byteswap is c++23.

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

No branches or pull requests

2 participants