[PATCH] erofs-utils: lib: fix base64 for tarerofs
Gao Xiang
hsiangkao at linux.alibaba.com
Wed Sep 10 11:45:07 AEST 2025
The old kernel fscrypt variant (fs/crypto/fname.c) was not real
RFC 4648 base64, see kernel commit ba47b515f594 ("fscrypt: align
Base64 encoding with RFC 4648 base64url").
Fixes: c0063a73b01b ("erofs-utils: lib: support importing xattrs from tarerofs")
Reported-by: Chengyu Zhu <hudsonzhu at tencent.com>
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
lib/Makefile.am | 3 +-
lib/base64.c | 69 +++++++++++++++++++++++++++++++++++++++++++
lib/liberofs_base64.h | 9 ++++++
lib/tar.c | 45 ++--------------------------
4 files changed, 83 insertions(+), 43 deletions(-)
create mode 100644 lib/base64.c
create mode 100644 lib/liberofs_base64.h
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 87454e3..daf937c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -27,6 +27,7 @@ noinst_HEADERS = $(top_srcdir)/include/erofs_fs.h \
$(top_srcdir)/include/erofs/fragments.h \
$(top_srcdir)/include/erofs/rebuild.h \
$(top_srcdir)/include/erofs/importer.h \
+ $(top_srcdir)/lib/liberofs_base64.h \
$(top_srcdir)/lib/liberofs_cache.h \
$(top_srcdir)/lib/liberofs_private.h \
$(top_srcdir)/lib/liberofs_xxhash.h \
@@ -40,7 +41,7 @@ liberofs_la_SOURCES = config.c io.c cache.c super.c inode.c xattr.c exclude.c \
compress_hints.c hashmap.c sha256.c blobchunk.c dir.c \
fragments.c dedupe.c uuid_unparse.c uuid.c tar.c \
block_list.c rebuild.c diskbuf.c bitops.c dedupe_ext.c \
- vmdk.c metabox.c global.c importer.c
+ vmdk.c metabox.c global.c importer.c base64.c
liberofs_la_CFLAGS = -Wall ${libuuid_CFLAGS} -I$(top_srcdir)/include
liberofs_la_LDFLAGS =
diff --git a/lib/base64.c b/lib/base64.c
new file mode 100644
index 0000000..c5f4ad8
--- /dev/null
+++ b/lib/base64.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
+#include "liberofs_base64.h"
+#include <string.h>
+
+static const char lookup_table[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int erofs_base64_encode(const u8 *src, int srclen, char *dst)
+{
+ u32 ac = 0;
+ int bits = 0;
+ int i;
+ char *cp = dst;
+
+ for (i = 0; i < srclen; i++) {
+ ac = (ac << 8) | src[i];
+ bits += 8;
+ do {
+ bits -= 6;
+ *cp++ = lookup_table[(ac >> bits) & 0x3f];
+ } while (bits >= 6);
+ }
+ if (bits) {
+ *cp++ = lookup_table[(ac << (6 - bits)) & 0x3f];
+ bits -= 6;
+ }
+ while (bits < 0) {
+ *cp++ = '=';
+ bits += 2;
+ }
+ return cp - dst;
+}
+
+int erofs_base64_decode(const char *src, int len, u8 *dst)
+{
+ int i, bits = 0, ac = 0;
+ const char *p;
+ u8 *cp = dst;
+ bool padding = false;
+
+ if(len && !(len % 4)) {
+ /* Check for and ignore any end padding */
+ if (src[len - 2] == '=' && src[len - 1] == '=')
+ len -= 2;
+ else if (src[len - 1] == '=')
+ --len;
+ padding = true;
+ }
+
+ for (i = 0; i < len; i++) {
+ p = strchr(lookup_table, src[i]);
+ if (!p || !src[i])
+ return -2;
+ ac = (ac << 6 | (p - lookup_table));
+ bits += 6;
+ if (bits >= 8) {
+ bits -= 8;
+ *cp++ = ac >> bits;
+ }
+ }
+ ac &= BIT(bits) - 1;
+ if (ac) {
+ if (padding || ac > 0xff)
+ return -1;
+ else
+ *cp++ = ac;
+ }
+ return cp - dst;
+}
diff --git a/lib/liberofs_base64.h b/lib/liberofs_base64.h
new file mode 100644
index 0000000..bcadb5f
--- /dev/null
+++ b/lib/liberofs_base64.h
@@ -0,0 +1,9 @@
+#ifndef __EROFS_LIB_LIBEROFS_BASE64_H
+#define __EROFS_LIB_LIBEROFS_BASE64_H
+
+#include "erofs/defs.h"
+
+int erofs_base64_encode(const u8 *src, int srclen, char *dst);
+int erofs_base64_decode(const char *src, int len, u8 *dst);
+
+#endif
diff --git a/lib/tar.c b/lib/tar.c
index c8fd48e..9dd1253 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -15,6 +15,7 @@
#if defined(HAVE_ZLIB)
#include <zlib.h>
#endif
+#include "liberofs_base64.h"
#include "liberofs_cache.h"
/* This file is a tape/volume header. Ignore it on extraction. */
@@ -400,46 +401,6 @@ int tarerofs_apply_xattrs(struct erofs_inode *inode, struct list_head *xattrs)
return 0;
}
-static const char lookup_table[65] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static int base64_decode(const char *src, int len, u8 *dst)
-{
- int i, bits = 0, ac = 0;
- const char *p;
- u8 *cp = dst;
- bool padding = false;
-
- if(len && !(len % 4)) {
- /* Check for and ignore any end padding */
- if (src[len - 2] == '=' && src[len - 1] == '=')
- len -= 2;
- else if (src[len - 1] == '=')
- --len;
- padding = true;
- }
-
- for (i = 0; i < len; i++) {
- p = strchr(lookup_table, src[i]);
- if (!p || !src[i])
- return -2;
- ac += (p - lookup_table) << bits;
- bits += 6;
- if (bits >= 8) {
- *cp++ = ac & 0xff;
- ac >>= 8;
- bits -= 8;
- }
- }
- if (ac) {
- if (padding || ac > 0xff)
- return -1;
- else
- *cp++ = ac & 0xff;
- }
- return cp - dst;
-}
-
static int tohex(int c)
{
if (c >= '0' && c <= '9')
@@ -594,8 +555,8 @@ int tarerofs_parse_pax_header(struct erofs_iostream *ios,
key = kv + sizeof("LIBARCHIVE.xattr.") - 1;
namelen = url_decode(key, value - key - 1);
--len; /* p[-1] == '\0' */
- ret = base64_decode(value, len - (value - kv),
- (u8 *)value);
+ ret = erofs_base64_decode(value, len - (value - kv),
+ (u8 *)value);
if (ret < 0) {
ret = -EFSCORRUPTED;
goto out;
--
2.43.5
More information about the Linux-erofs
mailing list