[colug-432] Jamming Bytes Into A uint64_t
jep200404 at columbus.rr.com
jep200404 at columbus.rr.com
Fri Feb 2 20:19:10 EST 2018
Here is some code to show some ways of jamming bytes into a uint64_t.
struct fait_accompli_struct deliberately has voids.
Notice how the data in the voids in the structure varies from run to run.
1.c does not overwrite the uint64_t buf.b. 1.c is the control.
2.c uses casting to access individual bytes of a uint64_t.
3.c uses a union to access individual bytes of a uint64_t.
2.c and 3.c are susceptible to byte order portability problems.
For that reason I am wary of using these techniques without knowing
more about the end use.
4.c always does things in host order.
Sometimes that is what you want. Sometimes it is not.
UINT64_AS_BYTES(i, x, y) is a very ugly macro.
UINT64_AS_BYTES(0, x, y) is always of the least significant byte
regardless of the machine's byte order.
and UINT64_AS_BYTES(7, x, y) is always of the most significant byte
regardless of the machine's byte order.
I highly recommend:
Advanced Programming in the UNIX Environment
W. Richard Stevens
Stephen A. Rago
W. Richard Stevens was an extraordinarly superb writer.
There is a third edition. I only have the first two editions.
In the second edition study, 16.3.1 Byte Ordering starting on p549.
Study:
man htonl
https://gnunet.org/book/export/html/363
-------------------------------------------------------------------------------
doj at sbc:~/byte-jammer$ head -v -n 1000 *.h *c
==> fait_accompli.h <==
/* Imagine that you can not change this header file
* (to put a union in for b). */
struct fait_accompli_struct {
/* ints were chosen to deliberately mess up the alignment.
* Study the output to see the voids in the structure.
* sizeof() can be deceptive. */
int a;
uint64_t b;
int c;
};
==> 1.c <==
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include "fait_accompli.h"
int main(int argc, char *argv[])
{
struct fait_accompli_struct buf;
int i;
buf.a = 0x11223344;
buf.c = 0x55667788;
buf.b = 0x0123456789ABCDEFUL;
i = write(STDOUT_FILENO, &buf, sizeof(buf));
fprintf(
stderr,
"i=%d sizeof(int)=%ld sizeof(uint64_t)=%ld sizeof(buf)=%ld\n",
i, sizeof(int), sizeof(uint64_t), sizeof(buf)
);
exit(EXIT_SUCCESS);
}
==> 2.c <==
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include "fait_accompli.h"
#define UINT64_AS_BYTES(x) ((unsigned char *)&(x))
int main(int argc, char *argv[])
{
struct fait_accompli_struct buf;
int i;
buf.a = 0x11223344;
buf.c = 0x55667788;
buf.b = 0x0123456789ABCDEFUL;
for (i = 0; i < 4; i++)
UINT64_AS_BYTES(buf.b)[i+2] = 'A' + i;
i = write(STDOUT_FILENO, &buf, sizeof(buf));
fprintf(
stderr,
"i=%d sizeof(int)=%ld sizeof(uint64_t)=%ld sizeof(buf)=%ld\n",
i, sizeof(int), sizeof(uint64_t), sizeof(buf)
);
exit(EXIT_SUCCESS);
}
==> 3.c <==
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include "fait_accompli.h"
union uint64_bytes_union {
uint64_t i;
unsigned char b[sizeof(uint64_t)];
};
int main(int argc, char *argv[])
{
struct fait_accompli_struct buf;
int i;
buf.a = 0x11223344;
buf.c = 0x55667788;
buf.b = 0x0123456789ABCDEFUL;
for (i = 0; i < 4; i++) {
union uint64_bytes_union *p = (void *)&buf.b;
p->b[i+2] = 'A' + i;
}
i = write(STDOUT_FILENO, &buf, sizeof(buf));
fprintf(
stderr,
"i=%d sizeof(int)=%ld sizeof(uint64_t)=%ld sizeof(buf)=%ld\n",
i, sizeof(int), sizeof(uint64_t), sizeof(buf)
);
exit(EXIT_SUCCESS);
}
==> 4.c <==
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include "fait_accompli.h"
#define MASK(width, offset) (((1UL<<(width)) - 1) << (offset))
#define UINT64_AS_BYTES(i, x, y) (\
((x) & ~MASK(8, 8*(i))) |\
((y) << (8*(i)))\
)
int main(int argc, char *argv[])
{
struct fait_accompli_struct buf;
int i;
buf.a = 0x11223344;
buf.c = 0x55667788;
buf.b = 0x0123456789ABCDEFUL;
for (i = 0; i < 4; i++)
buf.b = UINT64_AS_BYTES(
i+2, buf.b, (unsigned long)('A' + i)
);
i = write(STDOUT_FILENO, &buf, sizeof(buf));
fprintf(
stderr,
"i=%d sizeof(int)=%ld sizeof(uint64_t)=%ld sizeof(buf)=%ld\n",
i, sizeof(int), sizeof(uint64_t), sizeof(buf)
);
exit(EXIT_SUCCESS);
}
doj at sbc:~/byte-jammer$
The following were run on a 64-bit little-endian PC running 64-bit Ubuntu.
doj at sbc:~/byte-jammer$ ./1 | xxd -g 1 -u
i=24 sizeof(int)=4 sizeof(uint64_t)=8 sizeof(buf)=24
00000000: 44 33 22 11 00 00 00 00 EF CD AB 89 67 45 23 01 D3".........gE#.
00000010: 88 77 66 55 FF 7F 00 00 .wfU....
doj at sbc:~/byte-jammer$ ./2 | xxd -g 1 -u
i=24 sizeof(int)=4 sizeof(uint64_t)=8 sizeof(buf)=24
00000000: 44 33 22 11 00 00 00 00 EF CD 41 42 43 44 23 01 D3".......ABCD#.
00000010: 88 77 66 55 FE 7F 00 00 .wfU....
doj at sbc:~/byte-jammer$ ./3 | xxd -g 1 -u
i=24 sizeof(int)=4 sizeof(uint64_t)=8 sizeof(buf)=24
00000000: 44 33 22 11 00 00 00 00 EF CD 41 42 43 44 23 01 D3".......ABCD#.
00000010: 88 77 66 55 FF 7F 00 00 .wfU....
doj at sbc:~/byte-jammer$ ./4 | xxd -g 1 -u
i=24 sizeof(int)=4 sizeof(uint64_t)=8 sizeof(buf)=24
00000000: 44 33 22 11 00 00 00 00 EF CD 41 42 43 44 23 01 D3".......ABCD#.
00000010: 88 77 66 55 FE 7F 00 00 .wfU....
doj at sbc:~/byte-jammer$
Notice how the data in the structure voids can change from run to run.
doj at sbc:~/byte-jammer$ ./4 | xxd -g 1 -u
i=24 sizeof(int)=4 sizeof(uint64_t)=8 sizeof(buf)=24
00000000: 44 33 22 11 00 00 00 00 EF CD 41 42 43 44 23 01 D3".......ABCD#.
00000010: 88 77 66 55 FC 7F 00 00 .wfU....
doj at sbc:~/byte-jammer$ ./4 | xxd -g 1 -u
i=24 sizeof(int)=4 sizeof(uint64_t)=8 sizeof(buf)=24
00000000: 44 33 22 11 00 00 00 00 EF CD 41 42 43 44 23 01 D3".......ABCD#.
00000010: 88 77 66 55 FD 7F 00 00 .wfU....
doj at sbc:~/byte-jammer$ ./4 | xxd -g 1 -u
i=24 sizeof(int)=4 sizeof(uint64_t)=8 sizeof(buf)=24
00000000: 44 33 22 11 00 00 00 00 EF CD 41 42 43 44 23 01 D3".......ABCD#.
00000010: 88 77 66 55 FD 7F 00 00 .wfU....
doj at sbc:~/byte-jammer$
Hopefully someone will post the output of the following commands
run on a 64-bit big-endian computer.
./1 | xxd -g 1 -u
./2 | xxd -g 1 -u
./3 | xxd -g 1 -u
./4 | xxd -g 1 -u
More information about the colug-432
mailing list