Fix decoding of numeric and alphanumeric data types.
If the number of characters in the stream isn't a multiple of the full tuple size, the remaining characters are encoded in a special short tuple.
This commit is contained in:
parent
8d0eb68255
commit
0335fabf97
1 changed files with 71 additions and 36 deletions
103
lib/decode.c
103
lib/decode.c
|
@ -609,7 +609,7 @@ static quirc_decode_error_t codestream_ecc(struct quirc_data *data,
|
|||
return QUIRC_SUCCESS;
|
||||
}
|
||||
|
||||
static int get_bits(uint8_t *data, int pos, int len)
|
||||
static int get_bits(const uint8_t *data, int pos, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -627,13 +627,33 @@ static int get_bits(uint8_t *data, int pos, int len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int numeric_tuple(struct quirc_data *data,
|
||||
const struct datastream *ds,
|
||||
int *ptr, int bits, int digits)
|
||||
{
|
||||
int tuple;
|
||||
int i;
|
||||
|
||||
if (*ptr + bits > ds->data_bits)
|
||||
return -1;
|
||||
|
||||
tuple = get_bits(ds->data, *ptr, bits);
|
||||
*ptr += bits;
|
||||
|
||||
for (i = 0; i < digits; i++) {
|
||||
data->payload[data->payload_len++] = tuple % 10 + '0';
|
||||
tuple /= 10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static quirc_decode_error_t decode_numeric(struct quirc_data *data,
|
||||
struct datastream *ds)
|
||||
{
|
||||
int bits = 14;
|
||||
int count;
|
||||
int tuples;
|
||||
int i;
|
||||
int ptr;
|
||||
|
||||
if (data->version < 10)
|
||||
bits = 10;
|
||||
|
@ -644,36 +664,57 @@ static quirc_decode_error_t decode_numeric(struct quirc_data *data,
|
|||
if (count + 1 > QUIRC_MAX_PAYLOAD)
|
||||
return QUIRC_ERROR_DATA_OVERFLOW;
|
||||
|
||||
tuples = (count + 2) / 3;
|
||||
if (tuples * 10 + bits + 4 > ds->data_bits)
|
||||
data->payload_len = 0;
|
||||
ptr = bits + 4;
|
||||
|
||||
while (data->payload_len + 2 < count)
|
||||
if (numeric_tuple(data, ds, &ptr, 10, 3) < 0)
|
||||
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||
|
||||
for (i = 0; i < tuples; i++) {
|
||||
int d = get_bits(ds->data, i * 10 + bits + 4, 10);
|
||||
int p = i * 3 + 2;
|
||||
int j;
|
||||
if ((data->payload_len + 1 < count) &&
|
||||
(numeric_tuple(data, ds, &ptr, 7, 2) < 0))
|
||||
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (p < count)
|
||||
data->payload[p] = d % 10 + '0';
|
||||
d /= 10;
|
||||
p--;
|
||||
}
|
||||
}
|
||||
if ((data->payload_len < count) &&
|
||||
(numeric_tuple(data, ds, &ptr, 4, 1) < 0))
|
||||
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||
|
||||
data->payload[count] = 0;
|
||||
data->payload_len = count;
|
||||
|
||||
return QUIRC_SUCCESS;
|
||||
}
|
||||
|
||||
static int alpha_tuple(struct quirc_data *data,
|
||||
const struct datastream *ds,
|
||||
int *ptr, int bits, int digits)
|
||||
{
|
||||
int tuple;
|
||||
int i;
|
||||
|
||||
if (*ptr + bits > ds->data_bits)
|
||||
return -1;
|
||||
|
||||
tuple = get_bits(ds->data, *ptr, bits);
|
||||
*ptr += bits;
|
||||
|
||||
for (i = 0; i < digits; i++) {
|
||||
static const char *alpha_map =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
|
||||
|
||||
data->payload[data->payload_len + digits - i - 1] =
|
||||
alpha_map[tuple % 45];
|
||||
tuple /= 45;
|
||||
}
|
||||
|
||||
data->payload_len += digits;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static quirc_decode_error_t decode_alpha(struct quirc_data *data,
|
||||
struct datastream *ds)
|
||||
{
|
||||
int bits = 13;
|
||||
int count;
|
||||
int tuples;
|
||||
int i;
|
||||
int ptr;
|
||||
|
||||
if (data->version < 7)
|
||||
bits = 9;
|
||||
|
@ -684,24 +725,18 @@ static quirc_decode_error_t decode_alpha(struct quirc_data *data,
|
|||
if (count + 1 > QUIRC_MAX_PAYLOAD)
|
||||
return QUIRC_ERROR_DATA_OVERFLOW;
|
||||
|
||||
tuples = (count + 1) / 2;
|
||||
if (tuples * 11 + bits + 4 > ds->data_bits)
|
||||
data->payload_len = 0;
|
||||
ptr = bits + 4;
|
||||
|
||||
while (data->payload_len + 1 < count)
|
||||
if (alpha_tuple(data, ds, &ptr, 11, 2) < 0)
|
||||
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||
|
||||
for (i = 0; i < tuples; i++) {
|
||||
static const char *alpha_map =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
|
||||
int d = get_bits(ds->data, i * 11 + bits + 4, 11);
|
||||
int p = i * 2;
|
||||
|
||||
if (p + 1 < count)
|
||||
data->payload[p + 1] = alpha_map[d % 45];
|
||||
data->payload[p] = alpha_map[(d / 45) % 45];
|
||||
}
|
||||
if ((data->payload_len < count) &&
|
||||
(alpha_tuple(data, ds, &ptr, 6, 1) < 0))
|
||||
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||
|
||||
data->payload[count] = 0;
|
||||
data->payload_len = count;
|
||||
|
||||
return QUIRC_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue