]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_preopen: cap the queue length to the maximum number that fits into the digits...
authorStefan Metzmacher <metze@samba.org>
Fri, 18 Jun 2021 18:29:31 +0000 (18:29 +0000)
committerStefan Metzmacher <metze@samba.org>
Thu, 1 Jul 2021 13:02:31 +0000 (13:02 +0000)
If we have a single digit we only replace up to '9', which also fits
into a single digit.

We operate on numbers from 0 to 9999999999999999999 independent of the
architecture.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/modules/vfs_preopen.c

index 274149a01f1476ab7e480b96917d186c1314b64a..fa61d36d533a437208aa768927d86edda38f72de 100644 (file)
@@ -32,6 +32,9 @@ static int vfs_preopen_debug_level = DBGC_VFS;
 #undef DBGC_CLASS
 #define DBGC_CLASS vfs_preopen_debug_level
 
+#define PREOPEN_MAX_DIGITS 19
+#define PREOPEN_MAX_NUMBER (uint64_t)9999999999999999999ULL
+
 struct preopen_state;
 
 struct preopen_helper {
@@ -53,9 +56,9 @@ struct preopen_state {
        size_t number_start;    /* start offset into "template_fname" */
        int num_digits;         /* How many digits is the number long? */
 
-       int fnum_sent;          /* last fname sent to children */
+       uint64_t fnum_sent;     /* last fname sent to children */
 
-       int fnum_queue_end;     /* last fname to be sent, based on
+       uint64_t fnum_queue_end;/* last fname to be sent, based on
                                 * last open call + preopen:queuelen
                                 */
 
@@ -102,8 +105,8 @@ static void preopen_queue_run(struct preopen_state *state)
 
                snprintf(state->template_fname + state->number_start,
                         state->num_digits + 1,
-                        "%.*lu", state->num_digits,
-                        (long unsigned int)(state->fnum_sent + 1));
+                        "%.*llu", state->num_digits,
+                        (long long unsigned int)(state->fnum_sent + 1));
                *pdelimiter = delimiter;
 
                to_write = talloc_get_size(state->template_fname);
@@ -353,12 +356,12 @@ static struct preopen_state *preopen_state_get(vfs_handle_struct *handle)
        return state;
 }
 
-static bool preopen_parse_fname(const char *fname, unsigned long *pnum,
+static bool preopen_parse_fname(const char *fname, uint64_t *pnum,
                                size_t *pstart_idx, int *pnum_digits)
 {
        const char *p;
        char *q = NULL;
-       unsigned long num;
+       unsigned long long num;
        size_t start_idx = 0;
        int num_digits = -1;
        int error = 0;
@@ -382,12 +385,12 @@ static bool preopen_parse_fname(const char *fname, unsigned long *pnum,
 
        start_idx = (p - fname);
 
-       num = smb_strtoul(p, (char **)&q, 10, &error, SMB_STR_STANDARD);
+       num = smb_strtoull(p, (char **)&q, 10, &error, SMB_STR_STANDARD);
        if (error != 0) {
                return false;
        }
 
-       if (num+1 < num) {
+       if (num >= PREOPEN_MAX_NUMBER) {
                /* overflow */
                return false;
        }
@@ -400,6 +403,31 @@ static bool preopen_parse_fname(const char *fname, unsigned long *pnum,
        return true;
 }
 
+static uint64_t num_digits_max_value(int num_digits)
+{
+       uint64_t num_max = 1;
+       int i;
+
+       if (num_digits < 1) {
+               return 0;
+       }
+       if (num_digits >= PREOPEN_MAX_DIGITS) {
+               return PREOPEN_MAX_NUMBER;
+       }
+
+       for (i = 0; i < num_digits; i++) {
+               num_max *= 10;
+       }
+
+       /*
+        * We actually want
+        * 9   instead of 10
+        * 99  instead of 100
+        * 999 instead of 1000
+        */
+       return num_max - 1;
+}
+
 static int preopen_openat(struct vfs_handle_struct *handle,
                          const struct files_struct *dirfsp,
                          const struct smb_filename *smb_fname,
@@ -410,7 +438,8 @@ static int preopen_openat(struct vfs_handle_struct *handle,
        const char *dirname = dirfsp->fsp_name->base_name;
        struct preopen_state *state;
        int res;
-       unsigned long num;
+       uint64_t num;
+       uint64_t num_max;
        NTSTATUS status;
        char *new_template = NULL;
        size_t new_start = 0;
@@ -553,7 +582,8 @@ static int preopen_openat(struct vfs_handle_struct *handle,
                state->fnum_sent = num;
        }
 
-       state->fnum_queue_end = num + state->queue_max;
+       num_max = num_digits_max_value(state->num_digits);
+       state->fnum_queue_end = MIN(num_max, num + state->queue_max);
 
        preopen_queue_run(state);