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;
|
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;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -627,13 +627,33 @@ static int get_bits(uint8_t *data, int pos, int len)
|
||||||
return ret;
|
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,
|
static quirc_decode_error_t decode_numeric(struct quirc_data *data,
|
||||||
struct datastream *ds)
|
struct datastream *ds)
|
||||||
{
|
{
|
||||||
int bits = 14;
|
int bits = 14;
|
||||||
int count;
|
int count;
|
||||||
int tuples;
|
int ptr;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (data->version < 10)
|
if (data->version < 10)
|
||||||
bits = 10;
|
bits = 10;
|
||||||
|
@ -644,36 +664,57 @@ static quirc_decode_error_t decode_numeric(struct quirc_data *data,
|
||||||
if (count + 1 > QUIRC_MAX_PAYLOAD)
|
if (count + 1 > QUIRC_MAX_PAYLOAD)
|
||||||
return QUIRC_ERROR_DATA_OVERFLOW;
|
return QUIRC_ERROR_DATA_OVERFLOW;
|
||||||
|
|
||||||
tuples = (count + 2) / 3;
|
data->payload_len = 0;
|
||||||
if (tuples * 10 + bits + 4 > ds->data_bits)
|
ptr = bits + 4;
|
||||||
|
|
||||||
|
while (data->payload_len + 2 < count)
|
||||||
|
if (numeric_tuple(data, ds, &ptr, 10, 3) < 0)
|
||||||
return QUIRC_ERROR_DATA_UNDERFLOW;
|
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||||
|
|
||||||
for (i = 0; i < tuples; i++) {
|
if ((data->payload_len + 1 < count) &&
|
||||||
int d = get_bits(ds->data, i * 10 + bits + 4, 10);
|
(numeric_tuple(data, ds, &ptr, 7, 2) < 0))
|
||||||
int p = i * 3 + 2;
|
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j = 0; j < 3; j++) {
|
if ((data->payload_len < count) &&
|
||||||
if (p < count)
|
(numeric_tuple(data, ds, &ptr, 4, 1) < 0))
|
||||||
data->payload[p] = d % 10 + '0';
|
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||||
d /= 10;
|
|
||||||
p--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data->payload[count] = 0;
|
data->payload[count] = 0;
|
||||||
data->payload_len = count;
|
|
||||||
|
|
||||||
return QUIRC_SUCCESS;
|
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,
|
static quirc_decode_error_t decode_alpha(struct quirc_data *data,
|
||||||
struct datastream *ds)
|
struct datastream *ds)
|
||||||
{
|
{
|
||||||
int bits = 13;
|
int bits = 13;
|
||||||
int count;
|
int count;
|
||||||
int tuples;
|
int ptr;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (data->version < 7)
|
if (data->version < 7)
|
||||||
bits = 9;
|
bits = 9;
|
||||||
|
@ -684,24 +725,18 @@ static quirc_decode_error_t decode_alpha(struct quirc_data *data,
|
||||||
if (count + 1 > QUIRC_MAX_PAYLOAD)
|
if (count + 1 > QUIRC_MAX_PAYLOAD)
|
||||||
return QUIRC_ERROR_DATA_OVERFLOW;
|
return QUIRC_ERROR_DATA_OVERFLOW;
|
||||||
|
|
||||||
tuples = (count + 1) / 2;
|
data->payload_len = 0;
|
||||||
if (tuples * 11 + bits + 4 > ds->data_bits)
|
ptr = bits + 4;
|
||||||
|
|
||||||
|
while (data->payload_len + 1 < count)
|
||||||
|
if (alpha_tuple(data, ds, &ptr, 11, 2) < 0)
|
||||||
return QUIRC_ERROR_DATA_UNDERFLOW;
|
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||||
|
|
||||||
for (i = 0; i < tuples; i++) {
|
if ((data->payload_len < count) &&
|
||||||
static const char *alpha_map =
|
(alpha_tuple(data, ds, &ptr, 6, 1) < 0))
|
||||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
|
return QUIRC_ERROR_DATA_UNDERFLOW;
|
||||||
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];
|
|
||||||
}
|
|
||||||
|
|
||||||
data->payload[count] = 0;
|
data->payload[count] = 0;
|
||||||
data->payload_len = count;
|
|
||||||
|
|
||||||
return QUIRC_SUCCESS;
|
return QUIRC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue