Merge pull request #25653 from yuwata/base64_append
hexdecoct: several fixes for base64_append()
This commit is contained in:
+44
-26
@@ -59,11 +59,13 @@ char *hexmem(const void *p, size_t l) {
|
||||
const uint8_t *x;
|
||||
char *r, *z;
|
||||
|
||||
assert(p || l == 0);
|
||||
|
||||
z = r = new(char, l * 2 + 1);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
for (x = p; x < (const uint8_t*) p + l; x++) {
|
||||
for (x = p; x && x < (const uint8_t*) p + l; x++) {
|
||||
*(z++) = hexchar(*x >> 4);
|
||||
*(z++) = hexchar(*x & 15);
|
||||
}
|
||||
@@ -606,7 +608,7 @@ ssize_t base64mem_full(
|
||||
if (!r)
|
||||
return -ENOMEM;
|
||||
|
||||
for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
|
||||
for (x = p; x && x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
|
||||
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
|
||||
maybe_line_break(&z, r, line_break);
|
||||
*(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
|
||||
@@ -649,58 +651,74 @@ ssize_t base64mem_full(
|
||||
return z - r;
|
||||
}
|
||||
|
||||
static int base64_append_width(
|
||||
char **prefix, int plen,
|
||||
char sep, int indent,
|
||||
const void *p, size_t l,
|
||||
int width) {
|
||||
static ssize_t base64_append_width(
|
||||
char **prefix,
|
||||
size_t plen,
|
||||
char sep,
|
||||
size_t indent,
|
||||
const void *p,
|
||||
size_t l,
|
||||
size_t width) {
|
||||
|
||||
_cleanup_free_ char *x = NULL;
|
||||
char *t, *s;
|
||||
ssize_t len, avail, line, lines;
|
||||
size_t lines;
|
||||
ssize_t len;
|
||||
|
||||
assert(prefix);
|
||||
assert(*prefix || plen == 0);
|
||||
assert(p || l == 0);
|
||||
|
||||
len = base64mem(p, l, &x);
|
||||
if (len <= 0)
|
||||
if (len < 0)
|
||||
return len;
|
||||
if (len == 0)
|
||||
return plen;
|
||||
|
||||
lines = DIV_ROUND_UP(len, width);
|
||||
|
||||
if ((size_t) plen >= SSIZE_MAX - 1 - 1 ||
|
||||
if (plen >= SSIZE_MAX - 1 - 1 ||
|
||||
lines > (SSIZE_MAX - plen - 1 - 1) / (indent + width + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
t = realloc(*prefix, (ssize_t) plen + 1 + 1 + (indent + width + 1) * lines);
|
||||
t = realloc(*prefix, plen + 1 + 1 + (indent + width + 1) * lines);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
t[plen] = sep;
|
||||
s = t + plen;
|
||||
for (size_t line = 0; line < lines; line++) {
|
||||
size_t act = MIN(width, (size_t) len);
|
||||
|
||||
for (line = 0, s = t + plen + 1, avail = len; line < lines; line++) {
|
||||
int act = MIN(width, avail);
|
||||
if (line > 0)
|
||||
sep = '\n';
|
||||
|
||||
if (line > 0 || sep == '\n') {
|
||||
memset(s, ' ', indent);
|
||||
s += indent;
|
||||
if (s > t) {
|
||||
*s++ = sep;
|
||||
if (sep == '\n')
|
||||
s = mempset(s, ' ', indent);
|
||||
}
|
||||
|
||||
s = mempcpy(s, x + width * line, act);
|
||||
*(s++) = line < lines - 1 ? '\n' : '\0';
|
||||
avail -= act;
|
||||
len -= act;
|
||||
}
|
||||
assert(avail == 0);
|
||||
assert(len == 0);
|
||||
|
||||
*s = '\0';
|
||||
*prefix = t;
|
||||
return 0;
|
||||
return s - t;
|
||||
}
|
||||
|
||||
int base64_append(
|
||||
char **prefix, int plen,
|
||||
const void *p, size_t l,
|
||||
int indent, int width) {
|
||||
ssize_t base64_append(
|
||||
char **prefix,
|
||||
size_t plen,
|
||||
const void *p,
|
||||
size_t l,
|
||||
size_t indent,
|
||||
size_t width) {
|
||||
|
||||
if (plen > width / 2 || plen + indent > width)
|
||||
/* leave indent on the left, keep last column free */
|
||||
return base64_append_width(prefix, plen, '\n', indent, p, l, width - indent - 1);
|
||||
return base64_append_width(prefix, plen, '\n', indent, p, l, width - indent);
|
||||
else
|
||||
/* leave plen on the left, keep last column free */
|
||||
return base64_append_width(prefix, plen, ' ', plen + 1, p, l, width - plen - 1);
|
||||
|
||||
@@ -38,9 +38,13 @@ static inline ssize_t base64mem(const void *p, size_t l, char **ret) {
|
||||
return base64mem_full(p, l, SIZE_MAX, ret);
|
||||
}
|
||||
|
||||
int base64_append(char **prefix, int plen,
|
||||
const void *p, size_t l,
|
||||
int margin, int width);
|
||||
ssize_t base64_append(
|
||||
char **prefix,
|
||||
size_t plen,
|
||||
const void *p,
|
||||
size_t l,
|
||||
size_t margin,
|
||||
size_t width);
|
||||
int unbase64mem_full(const char *p, size_t l, bool secure, void **mem, size_t *len);
|
||||
static inline int unbase64mem(const char *p, size_t l, void **mem, size_t *len) {
|
||||
return unbase64mem_full(p, l, false, mem, len);
|
||||
|
||||
@@ -1889,6 +1889,36 @@ static int type_bitmap_to_json(Bitmap *b, JsonVariant **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int txt_to_json(DnsTxtItem *items, JsonVariant **ret) {
|
||||
JsonVariant **elements = NULL;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
LIST_FOREACH(items, i, items) {
|
||||
if (!GREEDY_REALLOC(elements, n + 1)) {
|
||||
r = -ENOMEM;
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
r = json_variant_new_octescape(elements + n, i->data, i->length);
|
||||
if (r < 0)
|
||||
goto finalize;
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
r = json_variant_new_array(ret, elements, n);
|
||||
|
||||
finalize:
|
||||
for (size_t i = 0; i < n; i++)
|
||||
json_variant_unref(elements[i]);
|
||||
|
||||
free(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
int dns_resource_record_to_json(DnsResourceRecord *rr, JsonVariant **ret) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *k = NULL;
|
||||
int r;
|
||||
@@ -1931,23 +1961,9 @@ int dns_resource_record_to_json(DnsResourceRecord *rr, JsonVariant **ret) {
|
||||
case DNS_TYPE_TXT: {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *l = NULL;
|
||||
|
||||
LIST_FOREACH(items, i, rr->txt.items) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *b = NULL;
|
||||
|
||||
r = json_variant_new_octescape(&b, i->data, i->length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_append_array(&l, b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!l) {
|
||||
r = json_variant_new_array(&l, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = txt_to_json(rr->txt.items, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return json_build(ret,
|
||||
JSON_BUILD_OBJECT(
|
||||
|
||||
@@ -73,6 +73,25 @@ TEST(undecchar) {
|
||||
assert_se(undecchar('9') == 9);
|
||||
}
|
||||
|
||||
static void test_hexmem_one(const char *in, const char *expected) {
|
||||
_cleanup_free_ char *result = NULL;
|
||||
_cleanup_free_ void *mem = NULL;
|
||||
size_t len;
|
||||
|
||||
assert_se(result = hexmem(in, strlen_ptr(in)));
|
||||
log_debug("hexmem(\"%s\") → \"%s\" (expected: \"%s\")", strnull(in), result, expected);
|
||||
assert_se(streq(result, expected));
|
||||
|
||||
assert_se(unhexmem(result, SIZE_MAX, &mem, &len) >= 0);
|
||||
assert_se(memcmp_safe(mem, in, len) == 0);
|
||||
}
|
||||
|
||||
TEST(hexmem) {
|
||||
test_hexmem_one(NULL, "");
|
||||
test_hexmem_one("", "");
|
||||
test_hexmem_one("foo", "666f6f");
|
||||
}
|
||||
|
||||
static void test_unhexmem_one(const char *s, size_t l, int retval) {
|
||||
_cleanup_free_ char *hex = NULL;
|
||||
_cleanup_free_ void *mem = NULL;
|
||||
@@ -308,6 +327,120 @@ TEST(base64mem_linebreak) {
|
||||
}
|
||||
}
|
||||
|
||||
static void test_base64_append_one(char **buf, size_t *len, const char *in, const char *expected) {
|
||||
ssize_t new_len;
|
||||
|
||||
new_len = base64_append(buf, *len, in, strlen_ptr(in), 8, 12);
|
||||
assert_se(new_len >= 0);
|
||||
log_debug("base64_append_one(\"%s\")\nresult:\n%s\nexpected:\n%s", in, strnull(*buf), strnull(expected));
|
||||
assert_se((size_t) new_len == strlen_ptr(*buf));
|
||||
assert_se(streq_ptr(*buf, expected));
|
||||
*len = new_len;
|
||||
}
|
||||
|
||||
TEST(base64_append) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
test_base64_append_one(&buf, &len, "", NULL);
|
||||
test_base64_append_one(&buf, &len, "f",
|
||||
"Zg==");
|
||||
test_base64_append_one(&buf, &len, "fo",
|
||||
"Zg== Zm8=");
|
||||
test_base64_append_one(&buf, &len, "foo",
|
||||
"Zg== Zm8=\n"
|
||||
" Zm9v");
|
||||
test_base64_append_one(&buf, &len, "foob",
|
||||
"Zg== Zm8=\n"
|
||||
" Zm9v\n"
|
||||
" Zm9v\n"
|
||||
" Yg==");
|
||||
test_base64_append_one(&buf, &len, "fooba",
|
||||
"Zg== Zm8=\n"
|
||||
" Zm9v\n"
|
||||
" Zm9v\n"
|
||||
" Yg==\n"
|
||||
" Zm9v\n"
|
||||
" YmE=");
|
||||
test_base64_append_one(&buf, &len, "foobar",
|
||||
"Zg== Zm8=\n"
|
||||
" Zm9v\n"
|
||||
" Zm9v\n"
|
||||
" Yg==\n"
|
||||
" Zm9v\n"
|
||||
" YmE=\n"
|
||||
" Zm9v\n"
|
||||
" YmFy");
|
||||
|
||||
assert_se(free_and_strdup(&buf, "hogehogehogehoge") >= 0);
|
||||
len = strlen(buf);
|
||||
|
||||
test_base64_append_one(&buf, &len, "",
|
||||
"hogehogehogehoge");
|
||||
test_base64_append_one(&buf, &len, "f",
|
||||
"hogehogehogehoge\n"
|
||||
" Zg==");
|
||||
test_base64_append_one(&buf, &len, "fo",
|
||||
"hogehogehogehoge\n"
|
||||
" Zg==\n"
|
||||
" Zm8=");
|
||||
test_base64_append_one(&buf, &len, "foo",
|
||||
"hogehogehogehoge\n"
|
||||
" Zg==\n"
|
||||
" Zm8=\n"
|
||||
" Zm9v");
|
||||
test_base64_append_one(&buf, &len, "foob",
|
||||
"hogehogehogehoge\n"
|
||||
" Zg==\n"
|
||||
" Zm8=\n"
|
||||
" Zm9v\n"
|
||||
" Zm9v\n"
|
||||
" Yg==");
|
||||
test_base64_append_one(&buf, &len, "fooba",
|
||||
"hogehogehogehoge\n"
|
||||
" Zg==\n"
|
||||
" Zm8=\n"
|
||||
" Zm9v\n"
|
||||
" Zm9v\n"
|
||||
" Yg==\n"
|
||||
" Zm9v\n"
|
||||
" YmE=");
|
||||
test_base64_append_one(&buf, &len, "foobar",
|
||||
"hogehogehogehoge\n"
|
||||
" Zg==\n"
|
||||
" Zm8=\n"
|
||||
" Zm9v\n"
|
||||
" Zm9v\n"
|
||||
" Yg==\n"
|
||||
" Zm9v\n"
|
||||
" YmE=\n"
|
||||
" Zm9v\n"
|
||||
" YmFy");
|
||||
|
||||
assert_se(free_and_strdup(&buf, "hogehogehogehoge") >= 0);
|
||||
len = strlen(buf);
|
||||
|
||||
test_base64_append_one(&buf, &len, "foobarfoobarfoobarfoobar",
|
||||
"hogehogehogehoge\n"
|
||||
" Zm9v\n"
|
||||
" YmFy\n"
|
||||
" Zm9v\n"
|
||||
" YmFy\n"
|
||||
" Zm9v\n"
|
||||
" YmFy\n"
|
||||
" Zm9v\n"
|
||||
" YmFy");
|
||||
|
||||
assert_se(free_and_strdup(&buf, "aaa") >= 0);
|
||||
len = strlen(buf);
|
||||
|
||||
test_base64_append_one(&buf, &len, "foobarfoobarfoobarfoobar",
|
||||
"aaa Zm9vYmFy\n"
|
||||
" Zm9vYmFy\n"
|
||||
" Zm9vYmFy\n"
|
||||
" Zm9vYmFy");
|
||||
}
|
||||
|
||||
static void test_unbase64mem_one(const char *input, const char *output, int ret) {
|
||||
_cleanup_free_ void *buffer = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user