Fix incorrect uint48_t sizing.

Resolve xsubi via ifunc if bitfield is placed in unexpected location within union.

Fortune for cpprng's current commit: Middle blessing − 中吉
lib
Avril 3 years ago
parent 2b24ab0408
commit ea4538231e
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -9,7 +9,6 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#define DEF(s, n) typedef s ## int ## n ## _t s ## n #define DEF(s, n) typedef s ## int ## n ## _t s ## n
#define DEFINT(n) typedef uint ## n ## _t u ## n; \ #define DEFINT(n) typedef uint ## n ## _t u ## n; \
typedef int ## n ## _t i ## n typedef int ## n ## _t i ## n

@ -9,8 +9,5 @@ namespace rng
{ {
private: private:
struct _inner;
// XXX: FUCK: This doesn't fucking work...
mem::aligned_ptr<jr_state> _state;
}; };
} }

@ -1,8 +1,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <assert.h>
#include <stdio.h>
#include "crand.h" #include "crand.h"
typedef unsigned short uint48_t[3];
struct jr_state struct jr_state
{ {
long result; long result;
@ -10,22 +16,46 @@ struct jr_state
union { union {
unsigned short xsubi[3]; unsigned short xsubi[3];
struct { struct {
unsigned int xsubh : 24; uint64_t xsubh : 48;
unsigned char _xsub : 8; uint16_t _xsub : 16;
}; };
unsigned int xsubl; uint64_t xsubl;
} st; } st;
}; };
_Static_assert( sizeof(uint48_t) == (sizeof(uint16_t) * 3), "bad uint48 (ushort[3])");
_Static_assert( sizeof(((struct jr_state*)NULL)->st) == sizeof(uint64_t), "bad uint64 (union st)");
static unsigned short* _impl__jr_st_resolv__low(struct jr_state* restrict state)
{
return state->st.xsubi;
}
void _jr_seed(struct jr_state* restrict state, unsigned int with) static unsigned short* _impl__jr_st_resolv__high(struct jr_state* restrict state)
{
return state->st.xsubi+1;
}
static unsigned short* (*_ifun__jr_st_resolv (void)) (struct jr_state* restrict state)
{
struct jr_state chk = {0};
chk.st.xsubh = JR_MAX;
return chk.st._xsub
? &_impl__jr_st_resolv__high
: &_impl__jr_st_resolv__low;
}
static unsigned short* _jr_st_resolv(struct jr_state* restrict state)
__attribute__((ifunc("_ifun__jr_st_resolv")));
void _jr_seed(struct jr_state* restrict state, unsigned long with)
{ {
state->st.xsubh = with; state->st.xsubh = with;
seed48_r(state->st.xsubi, &state->data); seed48_r(_jr_st_resolv(state), &state->data);
} }
long _jr_proc(struct jr_state* restrict state) long _jr_proc(struct jr_state* restrict state)
{ {
jrand48_r(state->st.xsubi, &state->data, &state->result); jrand48_r(_jr_st_resolv(state), &state->data, &state->result);
return state->result; return state->result;
} }
@ -41,3 +71,41 @@ void _jr_free(struct jr_state* restrict state)
{ {
free(state); free(state);
} }
//TODO: Use test macros from tracemac, run with attr(ctor) if `-DTEST` is provided.
void __TEST__jr_test()
{
struct jr_state* st = _jr_alloc();
assert(!st->st._xsub);
_jr_seed(st, ~0UL);
const volatile unsigned short* res_state = _jr_st_resolv(st);
printf("seeded: %lu (full %lu, spill %u). xsubi = [%04x, %04x, %04x) %04x], resolv = [%04x, %04x, %04x) %04x]\n", (uint64_t)st->st.xsubh, st->st.xsubl, st->st._xsub,
st->st.xsubi[0],
st->st.xsubi[1],
st->st.xsubi[2],
st->st.xsubi[3],
res_state[0],
res_state[1],
res_state[2],
res_state[3]);
assert(!st->st._xsub);
for(int i=0;i<10;i++)
{
printf("res: %ld\n", _jr_proc(st));
printf("state: %lu (full %lu, spill %u). xsubi = %p, resolv = %p\n", (uint64_t)st->st.xsubh, st->st.xsubl, st->st._xsub,
(const void*)st->st.xsubi, (const void*)_jr_st_resolv(st));
}
printf("ended: %lu (full %lu, spill %u). xsubi = [%04x, %04x, %04x) %04x], resolv = [%04x, %04x, %04x) %04x]\n", (uint64_t)st->st.xsubh, st->st.xsubl, st->st._xsub,
st->st.xsubi[0],
st->st.xsubi[1],
st->st.xsubi[2],
st->st.xsubi[3],
res_state[0],
res_state[1],
res_state[2],
res_state[3]);
assert(!st->st._xsub);
_jr_free(st);
}

@ -6,10 +6,10 @@
namespace rng namespace rng
{ {
struct crand::_inner { //struct crand::_inner {
//
jr_state st; // jr_state st;
}; //};
//TODO: Make header for rng::crand, a derived type of `Random`. //TODO: Make header for rng::crand, a derived type of `Random`.
} }

@ -3,7 +3,7 @@
#include <common.h> #include <common.h>
#define JR_MAX (UINT32_MAX >> 8) #define JR_MAX (UINT64_MAX >> 16)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -13,7 +13,7 @@ struct jr_state;
//TODO: make all these functions visibility("internal") //TODO: make all these functions visibility("internal")
void _jr_seed(struct jr_state* restrict state, unsigned int with); void _jr_seed(struct jr_state* restrict state, unsigned long with);
long _jr_proc(struct jr_state* restrict state); long _jr_proc(struct jr_state* restrict state);
struct jr_state* _jr_alloc(); struct jr_state* _jr_alloc();
void _jr_free(struct jr_state* restrict state); void _jr_free(struct jr_state* restrict state);

Loading…
Cancel
Save