Index | Thread | Search

From:
Thomas Habets <thomas@habets.se>
Subject:
find: fix mix of character block size check
To:
tech@openbsd.org
Date:
Mon, 18 May 2026 07:38:37 -0500

Download raw body.

Thread
Steps to reproduce:

```
  mkdir test
  dd if=/dev/zero of=test/hundred bs=100 count=1
  dd if=/dev/zero of=test/one bs=1 count=1
  find test -type f \( -size 1 -o -size 1c \) -print
```

Expected:

  File of size 1 and anything rounding up to 512 to match, meaning
  both files.

  `-size 1` matches both, so `-size 1 -o size 1c` should, too.

Actual:

  Only file of size 1 matched. `1` on the other side of the `-o` gets
  interpreted as `1c` too.

Problem:

  `divsize` is a global variable, not attached to the size constraint.

Patch:

Index: usr.bin/find/find.h
===================================================================
RCS file: /cvs/src/usr.bin/find/find.h,v
diff -u -p -u -p -r1.18 find.h
--- usr.bin/find/find.h 3 Jan 2017 21:31:16 -0000       1.18
+++ usr.bin/find/find.h 18 May 2026 12:28:29 -0000
@@ -69,7 +69,10 @@ typedef struct _plandata {
                        u_int _f_mask;
                } fl;
                nlink_t _l_data;                /* link count */
-               off_t _o_data;                  /* file size */
+               struct {
+                       off_t _o_data;          /* file size */
+                       int _o_divsize;         /* divide size into blocks */
+               } _sz_data;
                struct timespec _t_data;        /* time value */
                uid_t _u_data;                  /* uid */
                short _mt_data;                 /* mount flags */
@@ -103,7 +106,8 @@ typedef struct _plandata {
 #define        max_data        p_un._max_data
 #define        min_data        p_un._min_data
 #define        mt_data         p_un._mt_data
-#define        o_data          p_un._o_data
+#define        o_data          p_un._sz_data._o_data
+#define        o_divsize       p_un._sz_data._o_divsize
 #define        p_data          p_un._p_data
 #define        t_data          p_un._t_data
 #define        sec_data        p_un._t_data.tv_sec
Index: usr.bin/find/function.c
===================================================================
RCS file: /cvs/src/usr.bin/find/function.c,v
diff -u -p -u -p -r1.55 function.c
--- usr.bin/find/function.c     11 Aug 2023 04:45:05 -0000      1.55
+++ usr.bin/find/function.c     18 May 2026 12:28:29 -0000
@@ -1458,14 +1458,13 @@ c_prune(char *ignore, char ***ignored, i
  *     a c, the size is in bytes.
  */
 #define        FIND_SIZE       512
-static int divsize = 1;

 int
 f_size(PLAN *plan, FTSENT *entry)
 {
        off_t size;

-       size = divsize ? (entry->fts_statp->st_size + FIND_SIZE - 1) /
+       size = plan->o_divsize ? (entry->fts_statp->st_size + FIND_SIZE - 1) /
            FIND_SIZE : entry->fts_statp->st_size;
        COMPARE(size, plan->o_data);
 }
@@ -1481,8 +1480,9 @@ c_size(char *arg, char ***ignored, int u
        new = palloc(N_SIZE, f_size);
        endch = 'c';
        new->o_data = find_parsenum(new, "-size", arg, &endch);
+       new->o_divsize = 1;
        if (endch == 'c')
-               divsize = 0;
+               new->o_divsize = 0;
        return (new);
 }


Found with GPT 5.5, confirmed manually, and fixed jointly.

--
typedef struct me_s {
  char name[]      = { "Thomas Habets" };
  char email[]     = { "thomas@habets.se" };
  char kernel[]    = { "Linux" };
  char *pgpKey[]   = { "http://www.habets.pp.se/pubkey.txt" };
  char pgp[] = { "9907 8698 8A24 F52F 1C2E  87F6 39A4 9EEA 460A 0169" };
  char coolcmd[]   = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;