From bc3145617a8b1aa2f5f7050e9ba757f837af7494 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 26 Nov 2021 22:58:16 +0100 Subject: [PATCH] add input length argument to map_name() ... and use it when parsing IMAP LIST responses. --- src/common.h | 2 +- src/drv_imap.c | 6 +++--- src/main_sync.c | 2 +- src/sync.c | 2 +- src/util.c | 16 ++++++++++++---- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/common.h b/src/common.h index 9a25b56..b22a4cb 100644 --- a/src/common.h +++ b/src/common.h @@ -242,7 +242,7 @@ int ATTR_PRINTFLIKE(3, 4) nfsnprintf( char *buf, int blen, const char *fmt, ... void ATTR_NORETURN oob( void ); void ATTR_NORETURN oom( void ); -int map_name( const char *arg, char **result, uint reserve, const char *in, const char *out ); +int map_name( const char *arg, int argl, char **result, uint reserve, const char *in, const char *out ); int mkdir_p( char *path, int len ); diff --git a/src/drv_imap.c b/src/drv_imap.c index 4047baa..80cfbd7 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1491,8 +1491,8 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list ) } if (argl >= 5 && !memcmp( arg + argl - 5, ".lock", 5 )) /* workaround broken servers */ return LIST_OK; - if (map_name( arg, (char **)&narg, offsetof(string_list_t, string), ctx->delimiter, "/") < 0) { - warn( "IMAP warning: ignoring mailbox %s (reserved character '/' in name)\n", arg ); + if (map_name( arg, argl, (char **)&narg, offsetof(string_list_t, string), ctx->delimiter, "/") < 0) { + warn( "IMAP warning: ignoring mailbox %.*s (reserved character '/' in name)\n", argl, arg ); return LIST_OK; } // Validate the normalized name. Technically speaking, we could tolerate @@ -1533,7 +1533,7 @@ prepare_name( char **buf, const imap_store_t *ctx, const char *prefix, const cha { uint pl = strlen( prefix ); - switch (map_name( name, buf, pl, "/", ctx->delimiter )) { + switch (map_name( name, -1, buf, pl, "/", ctx->delimiter )) { case -1: error( "IMAP error: mailbox name %s contains server's hierarchy delimiter\n", name ); return -1; diff --git a/src/main_sync.c b/src/main_sync.c index 564a8a8..0c7f6db 100644 --- a/src/main_sync.c +++ b/src/main_sync.c @@ -527,7 +527,7 @@ store_listed( int sts, string_list_t *boxes, void *aux ) for (string_list_t *box = boxes; box; box = box->next) { if (mvars->ctx[t]->conf->flat_delim[0]) { string_list_t *nbox; - if (map_name( box->string, (char **)&nbox, offsetof(string_list_t, string), mvars->ctx[t]->conf->flat_delim, "/" ) < 0) { + if (map_name( box->string, -1, (char **)&nbox, offsetof(string_list_t, string), mvars->ctx[t]->conf->flat_delim, "/" ) < 0) { error( "Error: flattened mailbox name '%s' contains canonical hierarchy delimiter\n", box->string ); fail = 1; } else { diff --git a/src/sync.c b/src/sync.c index d37dfc0..48d5947 100644 --- a/src/sync.c +++ b/src/sync.c @@ -503,7 +503,7 @@ sync_boxes( store_t *ctx[], const char * const names[], int present[], channel_c "INBOX" : names[t]; if (!ctx[t]->conf->flat_delim[0]) { svars->box_name[t] = nfstrdup( svars->orig_name[t] ); - } else if (map_name( svars->orig_name[t], &svars->box_name[t], 0, "/", ctx[t]->conf->flat_delim ) < 0) { + } else if (map_name( svars->orig_name[t], -1, &svars->box_name[t], 0, "/", ctx[t]->conf->flat_delim ) < 0) { error( "Error: canonical mailbox name '%s' contains flattened hierarchy delimiter\n", svars->orig_name[t] ); bail3: svars->ret = SYNC_FAIL; diff --git a/src/util.c b/src/util.c index c020399..b999a8c 100644 --- a/src/util.c +++ b/src/util.c @@ -531,19 +531,21 @@ cur_user( void ) /* Return value: 0 = ok, -1 = out found in arg, -2 = in found in arg but no out specified */ int -map_name( const char *arg, char **result, uint reserve, const char *in, const char *out ) +map_name( const char *arg, int l, char **result, uint reserve, const char *in, const char *out ) { char *p; - uint i, l, ll, num, inl, outl; + int i, ll, num, inl, outl; assert( arg ); - l = strlen( arg ); + if (l < 0) + l = strlen( arg ); assert( in ); inl = strlen( in ); if (!inl) { copy: *result = nfmalloc( reserve + l + 1 ); - memcpy( *result + reserve, arg, l + 1 ); + memcpy( *result + reserve, arg, l ); + (*result)[reserve + l] = 0; return 0; } assert( out ); @@ -551,6 +553,8 @@ map_name( const char *arg, char **result, uint reserve, const char *in, const ch if (equals( in, (int)inl, out, outl )) goto copy; for (num = 0, i = 0; i < l; ) { + if (i + inl > l) + goto fout; for (ll = 0; ll < inl; ll++) if (arg[i + ll] != in[ll]) goto fout; @@ -559,6 +563,8 @@ map_name( const char *arg, char **result, uint reserve, const char *in, const ch continue; fout: if (outl) { + if (i + outl > l) + goto fnexti; for (ll = 0; ll < outl; ll++) if (arg[i + ll] != out[ll]) goto fnexti; @@ -574,6 +580,8 @@ map_name( const char *arg, char **result, uint reserve, const char *in, const ch *result = nfmalloc( reserve + l + num * (outl - inl) + 1 ); p = *result + reserve; for (i = 0; i < l; ) { + if (i + inl > l) + goto rnexti; for (ll = 0; ll < inl; ll++) if (arg[i + ll] != in[ll]) goto rnexti;