{"thread":{"id":"66638","subject":"[PATCH] [Outreachy PATCH] diff-delta: use safe integer arithmetic","startedAt":"2026-10-23T03:56:48Z","lastAt":"2026-10-27T16:57:46Z","messageCount":31,"participants":["Srujith A Poojary via GitGitGadget","Junio C Hamano","Srujith Poojary","Phillip Wood","Pablo Sabater"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"555940","messageId":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":null,"subject":"[PATCH] [Outreachy PATCH] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-23T03:56:48Z","receivedAt":"2026-10-23T03:56:48Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nReplace manual multiplication and addition in create_delta_index()\nwith safe integer helpers (st_mult, st_add, st_add3) to prevent\noverflows while preserving NULL returns on failure.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..45df070ab9 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t\tst_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\tst_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\tst_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"555945","messageId":"xmqqld7paty9.fsf@gitster.g","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"Re: [PATCH] [Outreachy PATCH] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-23T05:04:30Z","receivedAt":"2026-10-23T05:04:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Srujith A Poojary via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> From: Srujith A Poojary <poojarysrujith@gmail.com>\n>\n> Replace manual multiplication and addition in create_delta_index()\n> with safe integer helpers (st_mult, st_add, st_add3) to prevent\n> overflows while preserving NULL returns on failure.\n\nI do not quite understand what the last part of this explanation\nwants to say, i.e., \"while preserving NULL returns on failure\".  It\nmakes it sound as if the function would return NULL if the integer\nhelpers detect integer overflow, but I do not think that is what\nactually the updated code does at all.  st_add() and friends will\nsimply die() when overflow happens, so you will not even reach\nmalloc(), let alone return NULL when the malloc fails.\n\nAnd if you reply to this review message, please do not top-post.\n\nThanks.\n\n>\n> Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n> ---\n>     [Outreachy PATCH] diff-delta: use safe integer arithmetic\n>\n> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v1\n> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v1\n> Pull-Request: https://github.com/gitgitgadget/git/pull/2276\n>\n>  diff-delta.c | 10 +++++-----\n>  1 file changed, 5 insertions(+), 5 deletions(-)\n>\n> diff --git a/diff-delta.c b/diff-delta.c\n> index 7cbedeb507..45df070ab9 100644\n> --- a/diff-delta.c\n> +++ b/diff-delta.c\n> @@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>  \thmask = hsize - 1;\n>  \n>  \t/* allocate lookup index */\n> -\tmemsize = sizeof(*hash) * hsize +\n> -\t\t  sizeof(*entry) * entries;\n> +\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n> +\t\t\t\tst_mult(sizeof(*entry), entries));\n>  \tmem = malloc(memsize);\n>  \tif (!mem)\n>  \t\treturn NULL;\n> @@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>  \t * Now create the packed index in array form\n>  \t * rather than linked lists.\n>  \t */\n> -\tmemsize = sizeof(*index)\n> -\t\t+ sizeof(*packed_hash) * (hsize+1)\n> -\t\t+ sizeof(*packed_entry) * entries;\n> +\tmemsize = st_add3(sizeof(*index),\n> +\t\t\tst_mult(sizeof(*packed_hash), hsize + 1),\n> +\t\t\tst_mult(sizeof(*packed_entry), entries));\n>  \tmem = malloc(memsize);\n>  \tif (!mem) {\n>  \t\tfree(hash);\n>\n> base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n\n"},{"id":"555947","messageId":"CABh_KWiKmXP4KTgF=k2gGdSvcZXkRipD61AVn+AS7ZgvhcjHWw@mail.gmail.com","threadId":"66638","inReplyTo":"xmqqld7paty9.fsf@gitster.g","subject":"Re: [PATCH] [Outreachy PATCH] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-23T05:29:45Z","receivedAt":"2026-10-23T05:29:45Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Fri, Oct 23, 2026 at 10:34 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Srujith A Poojary via GitGitGadget\" <gitgitgadget@gmail.com>\n> writes:\n>\n> > From: Srujith A Poojary <poojarysrujith@gmail.com>\n> >\n> > Replace manual multiplication and addition in create_delta_index()\n> > with safe integer helpers (st_mult, st_add, st_add3) to prevent\n> > overflows while preserving NULL returns on failure.\n>\n> I do not quite understand what the last part of this explanation\n> wants to say, i.e., \"while preserving NULL returns on failure\".  It\n> makes it sound as if the function would return NULL if the integer\n> helpers detect integer overflow, but I do not think that is what\n> actually the updated code does at all.  st_add() and friends will\n> simply die() when overflow happens, so you will not even reach\n> malloc(), let alone return NULL when the malloc fails.\n>\n> And if you reply to this review message, please do not top-post.\n>\n> Thanks.\n>\n> >\n> > Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n> > ---\n> >     [Outreachy PATCH] diff-delta: use safe integer arithmetic\n> >\n> > Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v1\n> > Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v1\n> > Pull-Request: https://github.com/gitgitgadget/git/pull/2276\n> >\n> >  diff-delta.c | 10 +++++-----\n> >  1 file changed, 5 insertions(+), 5 deletions(-)\n> >\n> > diff --git a/diff-delta.c b/diff-delta.c\n> > index 7cbedeb507..45df070ab9 100644\n> > --- a/diff-delta.c\n> > +++ b/diff-delta.c\n> > @@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n> >       hmask = hsize - 1;\n> >\n> >       /* allocate lookup index */\n> > -     memsize = sizeof(*hash) * hsize +\n> > -               sizeof(*entry) * entries;\n> > +     memsize = st_add(st_mult(sizeof(*hash), hsize),\n> > +                             st_mult(sizeof(*entry), entries));\n> >       mem = malloc(memsize);\n> >       if (!mem)\n> >               return NULL;\n> > @@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n> >        * Now create the packed index in array form\n> >        * rather than linked lists.\n> >        */\n> > -     memsize = sizeof(*index)\n> > -             + sizeof(*packed_hash) * (hsize+1)\n> > -             + sizeof(*packed_entry) * entries;\n> > +     memsize = st_add3(sizeof(*index),\n> > +                     st_mult(sizeof(*packed_hash), hsize + 1),\n> > +                     st_mult(sizeof(*packed_entry), entries));\n> >       mem = malloc(memsize);\n> >       if (!mem) {\n> >               free(hash);\n> >\n> > base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n\nHi Junio,\n\nThank you for clarifying this. You are right—st_add() and st_mult()\ncall die() on overflow rather than returning NULL.\nI will update the commit message to accurately reflect this behavior\nand submit v2.\n\nBest regards,\nSrujith\n\n"},{"id":"555949","messageId":"pull.2276.v2.git.1792734993812.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v2] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-23T05:56:33Z","receivedAt":"2026-10-23T05:56:33Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nReplace manual multiplication and addition in create_delta_index()\nwith safe integer helpers (st_mult, st_add, st_add3) to prevent\noverflows.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v1:\n\n 1:  a0aafe63a7 ! 1:  14ffd630ca [Outreachy PATCH] diff-delta: use safe integer arithmetic\n     @@ Metadata\n      Author: Srujith A Poojary <poojarysrujith@gmail.com>\n      \n       ## Commit message ##\n     -    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n     +    diff-delta: use safe integer arithmetic\n      \n          Replace manual multiplication and addition in create_delta_index()\n          with safe integer helpers (st_mult, st_add, st_add3) to prevent\n     -    overflows while preserving NULL returns on failure.\n     +    overflows.\n      \n          Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n      \n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..45df070ab9 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t\tst_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\tst_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\tst_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556061","messageId":"fe3d651a-d1af-47a7-9b7b-a4ff242ca303@gmail.com","threadId":"66638","inReplyTo":"pull.2276.v2.git.1792734993812.gitgitgadget@gmail.com","subject":"Re: [PATCH v2] diff-delta: use safe integer arithmetic","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-10-23T15:15:47Z","receivedAt":"2026-10-23T15:15:47Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Srujith\n\nOn 23/10/2026 06:56, Srujith A Poojary via GitGitGadget wrote:\n> From: Srujith A Poojary <poojarysrujith@gmail.com>\n> > Replace manual multiplication and addition in create_delta_index()\n> with safe integer helpers (st_mult, st_add, st_add3) to prevent\n> overflows.\n\nSounds like a good idea\n\n> diff --git a/diff-delta.c b/diff-delta.c\n> index 7cbedeb507..45df070ab9 100644\n> --- a/diff-delta.c\n> +++ b/diff-delta.c\n> @@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>   \thmask = hsize - 1;\n>   >   \t/* allocate lookup index */\n> -\tmemsize = sizeof(*hash) * hsize +\n> -\t\t  sizeof(*entry) * entries;\n> +\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n> +\t\t\t\tst_mult(sizeof(*entry), entries));\n\nThe alignment is off here, see https://github.com/gitgitgadget/git/actions/runs/39906906057/job/120260845179?pr=2276 for a suggested fix from clang-format. I think you should be able to use \"git clang-format HEAD^\" to fix it.\n >   \tmem = malloc(memsize);\n>   \tif (!mem)\n>   \t\treturn NULL;\n> @@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>   \t * Now create the packed index in array form\n>   \t * rather than linked lists.\n>   \t */\n> -\tmemsize = sizeof(*index)\n> -\t\t+ sizeof(*packed_hash) * (hsize+1)\n> -\t\t+ sizeof(*packed_entry) * entries;\n> +\tmemsize = st_add3(sizeof(*index),\n> +\t\t\tst_mult(sizeof(*packed_hash), hsize + 1),\n\nWhat are the bounds of hsize? Can adding one to it overflow? The alignment is off here as well, all the arguments to st_add3() should be aligned.\n\nThanks\n\nPhillip\n\n> +\t\t\tst_mult(sizeof(*packed_entry), entries));\n>   \tmem = malloc(memsize);\n>   \tif (!mem) {\n>   \t\tfree(hash);\n> > base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n\n\n"},{"id":"556066","messageId":"xmqqtsmca0yy.fsf@gitster.g","threadId":"66638","inReplyTo":"CABh_KWiKmXP4KTgF=k2gGdSvcZXkRipD61AVn+AS7ZgvhcjHWw@mail.gmail.com","subject":"Re: [PATCH] [Outreachy PATCH] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-23T15:30:29Z","receivedAt":"2026-10-23T15:30:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Srujith Poojary <poojarysrujith@gmail.com> writes:\n\n> Thank you for clarifying this. You are right—st_add() and st_mult()\n> call die() on overflow rather than returning NULL.\n> I will update the commit message to accurately reflect this behavior\n> and submit v2.\n\nPlease don't, before making sure if it can overflow.  With the\nnumber of entries capped like this:\n\n\tif (bufsize >= 0xffffffffUL)\n\t\tentries = 0xfffffffeU / RABIN_WINDOW;\n\nand then computed\n\n\thsize = entries / 4;\n\tfor (i = 4; (1u << i) < hsize; i++);\n\thsize = 1 << i;\n\t/* allocate lookup index */\n\tmemsize = sizeof(*hash) * hsize +\n\t\t  sizeof(*entry) * entries;\n\nit may not be possible to overflow size_t even on 32-bit platforms.\nI didn't have time to do math yet myself, though.\n\n\n"},{"id":"556079","messageId":"CABh_KWgBzCXCSn4FUTSg+rXYj9vm6+AVZnDn3iR_4UJCsB8tjw@mail.gmail.com","threadId":"66638","inReplyTo":"xmqqtsmca0yy.fsf@gitster.g","subject":"Re: [PATCH] [Outreachy PATCH] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-23T16:56:13Z","receivedAt":"2026-10-23T16:56:13Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Fri, Oct 23, 2026 at 9:00 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Srujith Poojary <poojarysrujith@gmail.com> writes:\n>\n> > Thank you for clarifying this. You are right—st_add() and st_mult()\n> > call die() on overflow rather than returning NULL.\n> > I will update the commit message to accurately reflect this behavior\n> > and submit v2.\n>\n> Please don't, before making sure if it can overflow.  With the\n> number of entries capped like this:\n>\n>         if (bufsize >= 0xffffffffUL)\n>                 entries = 0xfffffffeU / RABIN_WINDOW;\n>\n> and then computed\n>\n>         hsize = entries / 4;\n>         for (i = 4; (1u << i) < hsize; i++);\n>         hsize = 1 << i;\n>         /* allocate lookup index */\n>         memsize = sizeof(*hash) * hsize +\n>                   sizeof(*entry) * entries;\n>\n> it may not be possible to overflow size_t even on 32-bit platforms.\n> I didn't have time to do math yet myself, though.\n>\n\nHi Phillip and Junio,\n\nThank you for the detailed feedback.\n\nI checked the bounds: since entries is capped by (0xffffffu /\nRABIN_WINDOW), hsize remains small, making a size_t overflow\nimpossible even on 32-bit systems.\n\nI ran git clang-format HEAD^ to fix the code alignment as suggested\nand updated the patch.\n\nBest regards,\nSrujith\n\n"},{"id":"556097","messageId":"xmqqcxt05k8r.fsf@gitster.g","threadId":"66638","inReplyTo":"CABh_KWgBzCXCSn4FUTSg+rXYj9vm6+AVZnDn3iR_4UJCsB8tjw@mail.gmail.com","subject":"Re: [PATCH] [Outreachy PATCH] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-23T18:45:24Z","receivedAt":"2026-10-23T18:45:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Srujith Poojary <poojarysrujith@gmail.com> writes:\n\n> On Fri, Oct 23, 2026 at 9:00 PM Junio C Hamano <gitster@pobox.com> wrote:\n>>\n>> Srujith Poojary <poojarysrujith@gmail.com> writes:\n>>\n>> > Thank you for clarifying this. You are right—st_add() and st_mult()\n>> > call die() on overflow rather than returning NULL.\n>> > I will update the commit message to accurately reflect this behavior\n>> > and submit v2.\n>>\n>> Please don't, before making sure if it can overflow.  With the\n>> number of entries capped like this:\n>>\n>>         if (bufsize >= 0xffffffffUL)\n>>                 entries = 0xfffffffeU / RABIN_WINDOW;\n>>\n>> and then computed\n>>\n>>         hsize = entries / 4;\n>>         for (i = 4; (1u << i) < hsize; i++);\n>>         hsize = 1 << i;\n>>         /* allocate lookup index */\n>>         memsize = sizeof(*hash) * hsize +\n>>                   sizeof(*entry) * entries;\n>>\n>> it may not be possible to overflow size_t even on 32-bit platforms.\n>> I didn't have time to do math yet myself, though.\n>>\n>\n> Hi Phillip and Junio,\n>\n> Thank you for the detailed feedback.\n>\n> I checked the bounds: since entries is capped by (0xffffffu /\n> RABIN_WINDOW), hsize remains small, making a size_t overflow\n> impossible even on 32-bit systems.\n\nHmph, I actually came to a different conclusion, but my math is\nprobably weaker X-<.\n\nentries is capped by 1^32 / 16 = 1^28, and hsize is capped at 1^26.\n\nsizeof(*hash) is 4 bytes on 32-bit platforms.\n\nstruct index_entry has a pointer and an unsigned, i.e. 8 bytes.\nstruct unpacked_index_entry has the above index_entry plus a\npointer, i.e. 8+4=12 bytes or 16 bytes (with 4-byte padding).\nThat is the sizeof(*entry).\n\nIf \"struct unpacked_index_entry\" has 4-byte padding to align at\n8-byte boundary, then memsize = 4 * 1^26 + 16 * 1^28 can overflow\nsize_t's range that is 1^32.  If the struct does not have extra\npadding, this would fit below 1^32.  We have no guarantee what the\ncompiler would do, so we need to assume the worst.\n\nOf course it is entirely a different matter if malloc() would allow\nsuch a large allocation even if math does not overflow, but the\nfocus of this patch is to make sure memsize is computed as a large\nallocation in such a case without wrapping around.\n\n\n"},{"id":"556099","messageId":"xmqq8q3o5k1q.fsf@gitster.g","threadId":"66638","inReplyTo":"fe3d651a-d1af-47a7-9b7b-a4ff242ca303@gmail.com","subject":"Re: [PATCH v2] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-23T18:49:37Z","receivedAt":"2026-10-23T18:49:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>> +\tmemsize = st_add3(sizeof(*index),\n>> +\t\t\tst_mult(sizeof(*packed_hash), hsize + 1),\n>\n> What are the bounds of hsize? Can adding one to it overflow? The \n> alignment is off here as well, all the arguments to st_add3() should be \n> aligned.\n\nVery good question, and I think hsize is capped at 1^26 in a code\nearly in this function, which makes this safe.  It needs to be\nexplained why it is safe in the log message, though.\n\n"},{"id":"556136","messageId":"CABh_KWj9wbanf6MSscwfurkgsaSgJvL_tg17sTt69TfWufnVyQ@mail.gmail.com","threadId":"66638","inReplyTo":"xmqq8q3o5k1q.fsf@gitster.g","subject":"Re: [PATCH v2] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-24T03:44:47Z","receivedAt":"2026-10-24T03:44:47Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Sat, Oct 24, 2026 at 12:19 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n>\n> >> +    memsize = st_add3(sizeof(*index),\n> >> +                    st_mult(sizeof(*packed_hash), hsize + 1),\n> >\n> > What are the bounds of hsize? Can adding one to it overflow? The\n> > alignment is off here as well, all the arguments to st_add3() should be\n> > aligned.\n>\n> Very good question, and I think hsize is capped at 1^26 in a code\n> early in this function, which makes this safe.  It needs to be\n> explained why it is safe in the log message, though.\n\nHi Junio,\n\nThank you for analyzing the struct alignment and memory allocation limits.\nI have updated the commit message to explain why st_mult/st_add are\nnecessary on 32-bit platforms due to padding, as well as documenting\nthat hsize + 1 is safe because hsize is capped at 2^26.\nI also fixed the code formatting using git clang-format HEAD^.\n\nBest regards,\nSrujith\n\n"},{"id":"556137","messageId":"pull.2276.v3.git.1792813697888.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v3] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-24T03:48:17Z","receivedAt":"2026-10-24T03:48:17Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nReplace manual multiplication and addition in create_delta_index()\nwith safe integer helpers (st_mult, st_add, st_add3) to prevent potential\noverflows when computing memory allocation sizes.\n\nOn 32-bit platforms, struct alignment padding could cause the total\nallocation size calculation to exceed 2^32, making safe integer arithmetic\nnecessary. Note that hsize + 1 inside st_add3() is safe from overflow\nbecause hsize is capped at 2^26 early in the function.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v3\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v2:\n\n 1:  14ffd630ca ! 1:  d288bfe9e3 diff-delta: use safe integer arithmetic\n     @@ Commit message\n          diff-delta: use safe integer arithmetic\n      \n          Replace manual multiplication and addition in create_delta_index()\n     -    with safe integer helpers (st_mult, st_add, st_add3) to prevent\n     -    overflows.\n     +    with safe integer helpers (st_mult, st_add, st_add3) to prevent potential\n     +    overflows when computing memory allocation sizes.\n     +\n     +    On 32-bit platforms, struct alignment padding could cause the total\n     +    allocation size calculation to exceed 2^32, making safe integer arithmetic\n     +    necessary. Note that hsize + 1 inside st_add3() is safe from overflow\n     +    because hsize is capped at 2^26 early in the function.\n      \n          Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n      \n     @@ diff-delta.c: struct delta_index * create_delta_index(const void *buf, size_t bu\n      -\tmemsize = sizeof(*hash) * hsize +\n      -\t\t  sizeof(*entry) * entries;\n      +\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n     -+\t\t\t\tst_mult(sizeof(*entry), entries));\n     ++\t\t\t st_mult(sizeof(*entry), entries));\n       \tmem = malloc(memsize);\n       \tif (!mem)\n       \t\treturn NULL;\n     @@ diff-delta.c: struct delta_index * create_delta_index(const void *buf, size_t bu\n      -\t\t+ sizeof(*packed_hash) * (hsize+1)\n      -\t\t+ sizeof(*packed_entry) * entries;\n      +\tmemsize = st_add3(sizeof(*index),\n     -+\t\t\tst_mult(sizeof(*packed_hash), hsize + 1),\n     -+\t\t\tst_mult(sizeof(*packed_entry), entries));\n     ++\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n     ++\t\t\t  st_mult(sizeof(*packed_entry), entries));\n       \tmem = malloc(memsize);\n       \tif (!mem) {\n       \t\tfree(hash);\n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..efebce3aca 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t st_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\t  st_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556172","messageId":"xmqqfqxv13d6.fsf@gitster.g","threadId":"66638","inReplyTo":"pull.2276.v3.git.1792813697888.gitgitgadget@gmail.com","subject":"Re: [PATCH v3] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-24T16:15:49Z","receivedAt":"2026-10-24T16:15:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Srujith A Poojary via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> From: Srujith A Poojary <poojarysrujith@gmail.com>\n>\n> Replace manual multiplication and addition in create_delta_index()\n> with safe integer helpers (st_mult, st_add, st_add3) to prevent potential\n> overflows when computing memory allocation sizes.\n>\n> On 32-bit platforms, struct alignment padding could cause the total\n> allocation size calculation to exceed 2^32, making safe integer arithmetic\n> necessary.\n\nI wonder if \"X could cause Y\" above skips a bit too many steps.  I\nwas expecting more along the lines of ...\n\n    We will need to allocate N instances of A and M instances of B, N\n    and M are capped to X and Y respectively by this code\n\n        ... code snippet ...\n\n    and size of an instance of A is 8 and size of B could be either W or\n    Z.  When size of B is W, then the total allocation would be ...\n\nAnd that analysis applies only on the first allocation.  I didn't\neven look at the packed side of the allocation size, expecting that\nyou would know how to analyze after seeing my example on the other\nallocation.\n\n> Note that hsize + 1 inside st_add3() is safe from overflow\n> because hsize is capped at 2^26 early in the function.\n\nIt is misleading to say hsize+1 is inside st_add3(), though.\n\n\n> diff --git a/diff-delta.c b/diff-delta.c\n> index 7cbedeb507..efebce3aca 100644\n> --- a/diff-delta.c\n> +++ b/diff-delta.c\n> @@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>  \thmask = hsize - 1;\n>  \n>  \t/* allocate lookup index */\n> -\tmemsize = sizeof(*hash) * hsize +\n> -\t\t  sizeof(*entry) * entries;\n> +\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n> +\t\t\t st_mult(sizeof(*entry), entries));\n>  \tmem = malloc(memsize);\n>  \tif (!mem)\n>  \t\treturn NULL;\n> @@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>  \t * Now create the packed index in array form\n>  \t * rather than linked lists.\n>  \t */\n> -\tmemsize = sizeof(*index)\n> -\t\t+ sizeof(*packed_hash) * (hsize+1)\n> -\t\t+ sizeof(*packed_entry) * entries;\n> +\tmemsize = st_add3(sizeof(*index),\n> +\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n> +\t\t\t  st_mult(sizeof(*packed_entry), entries));\n>  \tmem = malloc(memsize);\n>  \tif (!mem) {\n>  \t\tfree(hash);\n>\n> base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n\n"},{"id":"556179","messageId":"CABh_KWhDcPM6rJROmVd7_oGZ7i3tmX5da-DZX=KJmvSyCxNH_A@mail.gmail.com","threadId":"66638","inReplyTo":"xmqqfqxv13d6.fsf@gitster.g","subject":"Re: [PATCH v3] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-24T17:26:08Z","receivedAt":"2026-10-24T17:26:08Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Sat, Oct 24, 2026 at 9:45 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Srujith A Poojary via GitGitGadget\" <gitgitgadget@gmail.com>\n> writes:\n>\n> > From: Srujith A Poojary <poojarysrujith@gmail.com>\n> >\n> > Replace manual multiplication and addition in create_delta_index()\n> > with safe integer helpers (st_mult, st_add, st_add3) to prevent potential\n> > overflows when computing memory allocation sizes.\n> >\n> > On 32-bit platforms, struct alignment padding could cause the total\n> > allocation size calculation to exceed 2^32, making safe integer arithmetic\n> > necessary.\n>\n> I wonder if \"X could cause Y\" above skips a bit too many steps.  I\n> was expecting more along the lines of ...\n>\n>     We will need to allocate N instances of A and M instances of B, N\n>     and M are capped to X and Y respectively by this code\n>\n>         ... code snippet ...\n>\n>     and size of an instance of A is 8 and size of B could be either W or\n>     Z.  When size of B is W, then the total allocation would be ...\n>\n> And that analysis applies only on the first allocation.  I didn't\n> even look at the packed side of the allocation size, expecting that\n> you would know how to analyze after seeing my example on the other\n> allocation.\n>\n> > Note that hsize + 1 inside st_add3() is safe from overflow\n> > because hsize is capped at 2^26 early in the function.\n>\n> It is misleading to say hsize+1 is inside st_add3(), though.\n>\n>\n> > diff --git a/diff-delta.c b/diff-delta.c\n> > index 7cbedeb507..efebce3aca 100644\n> > --- a/diff-delta.c\n> > +++ b/diff-delta.c\n> > @@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n> >       hmask = hsize - 1;\n> >\n> >       /* allocate lookup index */\n> > -     memsize = sizeof(*hash) * hsize +\n> > -               sizeof(*entry) * entries;\n> > +     memsize = st_add(st_mult(sizeof(*hash), hsize),\n> > +                      st_mult(sizeof(*entry), entries));\n> >       mem = malloc(memsize);\n> >       if (!mem)\n> >               return NULL;\n> > @@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n> >        * Now create the packed index in array form\n> >        * rather than linked lists.\n> >        */\n> > -     memsize = sizeof(*index)\n> > -             + sizeof(*packed_hash) * (hsize+1)\n> > -             + sizeof(*packed_entry) * entries;\n> > +     memsize = st_add3(sizeof(*index),\n> > +                       st_mult(sizeof(*packed_hash), hsize + 1),\n> > +                       st_mult(sizeof(*packed_entry), entries));\n> >       mem = malloc(memsize);\n> >       if (!mem) {\n> >               free(hash);\n> >\n> > base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n\nHi Junio,\n\nThank you for the detailed correction.\n\nI have expanded the commit message to include the step-by-step\nbreakdown for both the unpacked and packed index allocations,\ndetailing the caps on hsize (2^26) and entries (2^28) alongside struct\npadding on 32-bit systems. I also corrected the phrasing regarding\n(hsize + 1) being passed as an argument to st_add3().\n\nI have updated the patch series accordingly.\n\nBest regards,\nSrujith\n\n"},{"id":"556181","messageId":"pull.2276.v4.git.1792864857176.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v4] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-24T18:00:57Z","receivedAt":"2026-10-24T18:00:57Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nReplace manual multiplication and addition in create_delta_index()\nwith safe integer helpers (st_mult, st_add, st_add3) to prevent potential\noverflows when computing memory allocation sizes.\n\nFor the unpacked index, we allocate hsize instances of hash pointers and\nentries instances of struct index_entry:\n  - hsize is capped at 2^26.\n  - entries is capped at 2^28.\nOn 32-bit platforms with 4-byte padding for struct unpacked_index_entry,\nthe calculation size (sizeof(*hash) * hsize + sizeof(*entry) * entries) can\nexceed 2^32, making safe integer arithmetic necessary.\n\nSimilarly, for the packed index, we compute allocation size across\nstruct index, packed_hash, and entries. Using safe helpers prevents\nwrap-around across both allocations.\n\nNote that passing (hsize + 1) as an argument to st_add3() is safe from\noverflow because hsize is capped at 2^26 early in the function.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v4\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v4\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v3:\n\n 1:  d288bfe9e3 ! 1:  0d5a729cde diff-delta: use safe integer arithmetic\n     @@ Commit message\n          with safe integer helpers (st_mult, st_add, st_add3) to prevent potential\n          overflows when computing memory allocation sizes.\n      \n     -    On 32-bit platforms, struct alignment padding could cause the total\n     -    allocation size calculation to exceed 2^32, making safe integer arithmetic\n     -    necessary. Note that hsize + 1 inside st_add3() is safe from overflow\n     -    because hsize is capped at 2^26 early in the function.\n     +    For the unpacked index, we allocate hsize instances of hash pointers and\n     +    entries instances of struct index_entry:\n     +      - hsize is capped at 2^26.\n     +      - entries is capped at 2^28.\n     +    On 32-bit platforms with 4-byte padding for struct unpacked_index_entry,\n     +    the calculation size (sizeof(*hash) * hsize + sizeof(*entry) * entries) can\n     +    exceed 2^32, making safe integer arithmetic necessary.\n     +\n     +    Similarly, for the packed index, we compute allocation size across\n     +    struct index, packed_hash, and entries. Using safe helpers prevents\n     +    wrap-around across both allocations.\n     +\n     +    Note that passing (hsize + 1) as an argument to st_add3() is safe from\n     +    overflow because hsize is capped at 2^26 early in the function.\n      \n          Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n      \n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..efebce3aca 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t st_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\t  st_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556219","messageId":"xmqqmrs1y7kj.fsf@gitster.g","threadId":"66638","inReplyTo":"CABh_KWhDcPM6rJROmVd7_oGZ7i3tmX5da-DZX=KJmvSyCxNH_A@mail.gmail.com","subject":"Re: [PATCH v3] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-25T18:10:52Z","receivedAt":"2026-10-25T18:10:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Srujith Poojary <poojarysrujith@gmail.com> writes:\n\n> Thank you for the detailed correction.\n>\n> I have expanded the commit message to include the step-by-step\n> breakdown for both the unpacked and packed index allocations,\n> detailing the caps on hsize (2^26) and entries (2^28) alongside struct\n> padding on 32-bit systems. I also corrected the phrasing regarding\n> (hsize + 1) being passed as an argument to st_add3().\n\nIt seems that the text of v4 did not \"detail\" anything like that;\nyou just parroted the conclusion, the final numbers I gave you,\nwithout giving any hint for the readers to validate the math.  The\nreaders who are interested in validating are forced to figure out\nhow many bytes your calculation assumes each struct type involved\nconsume---and if they find that your conclusion is wrong, they have\nno clue where in your computation things went wrong.\n\n\n"},{"id":"556225","messageId":"pull.2276.v5.git.1792956031588.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v5] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-25T19:20:31Z","receivedAt":"2026-10-25T19:20:31Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nIn create_delta_index(), buffer sizes for allocating the delta index\nare calculated using arithmetic operations on entries and hsize:\n\n  memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n\nTo prevent potential size_t wrap-around when computing allocation sizes\non 32-bit systems, replace manual arithmetic with overflow-checked\nhelpers (st_mult, st_add, st_add3).\n\nFor the unpacked index allocation:\n- sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n  which may be padded to 16 bytes depending on compiler alignment rules.\n- sizeof(struct index_entry *) is 4 bytes.\n- entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n  limiting entries to 1,048,575.\n- hsize is the smallest power of 2 greater than or equal to entries,\n  capped at 1,048,576.\n\nWhile entries is bounded in current code, using st_mult() and st_add()\nguarantees that any unexpected growth in struct sizes or bounds changes\nwill safely die() on size_t overflow instead of wrapping around.\n\nFor the packed index allocation:\n- Passing (hsize + 1) as an argument to st_add3() is safe from overflow\n  because hsize is capped at 1,048,576 early in the function.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v5\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v5\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v4:\n\n 1:  0d5a729cde ! 1:  23fcfd3227 diff-delta: use safe integer arithmetic\n     @@ Metadata\n       ## Commit message ##\n          diff-delta: use safe integer arithmetic\n      \n     -    Replace manual multiplication and addition in create_delta_index()\n     -    with safe integer helpers (st_mult, st_add, st_add3) to prevent potential\n     -    overflows when computing memory allocation sizes.\n     -\n     -    For the unpacked index, we allocate hsize instances of hash pointers and\n     -    entries instances of struct index_entry:\n     -      - hsize is capped at 2^26.\n     -      - entries is capped at 2^28.\n     -    On 32-bit platforms with 4-byte padding for struct unpacked_index_entry,\n     -    the calculation size (sizeof(*hash) * hsize + sizeof(*entry) * entries) can\n     -    exceed 2^32, making safe integer arithmetic necessary.\n     -\n     -    Similarly, for the packed index, we compute allocation size across\n     -    struct index, packed_hash, and entries. Using safe helpers prevents\n     -    wrap-around across both allocations.\n     -\n     -    Note that passing (hsize + 1) as an argument to st_add3() is safe from\n     -    overflow because hsize is capped at 2^26 early in the function.\n     +    In create_delta_index(), buffer sizes for allocating the delta index\n     +    are calculated using arithmetic operations on entries and hsize:\n     +\n     +      memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n     +\n     +    To prevent potential size_t wrap-around when computing allocation sizes\n     +    on 32-bit systems, replace manual arithmetic with overflow-checked\n     +    helpers (st_mult, st_add, st_add3).\n     +\n     +    For the unpacked index allocation:\n     +    - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n     +      which may be padded to 16 bytes depending on compiler alignment rules.\n     +    - sizeof(struct index_entry *) is 4 bytes.\n     +    - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n     +      limiting entries to 1,048,575.\n     +    - hsize is the smallest power of 2 greater than or equal to entries,\n     +      capped at 1,048,576.\n     +\n     +    While entries is bounded in current code, using st_mult() and st_add()\n     +    guarantees that any unexpected growth in struct sizes or bounds changes\n     +    will safely die() on size_t overflow instead of wrapping around.\n     +\n     +    For the packed index allocation:\n     +    - Passing (hsize + 1) as an argument to st_add3() is safe from overflow\n     +      because hsize is capped at 1,048,576 early in the function.\n      \n          Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n      \n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..efebce3aca 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t st_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\t  st_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556226","messageId":"CABh_KWhE1eWYt60TvcN_7sAe6ORut2YH7a5Zmu2zLobv=VSefg@mail.gmail.com","threadId":"66638","inReplyTo":"xmqqmrs1y7kj.fsf@gitster.g","subject":"Re: [PATCH v3] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-25T19:21:22Z","receivedAt":"2026-10-25T19:21:22Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Sun, Oct 25, 2026 at 11:40 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Srujith Poojary <poojarysrujith@gmail.com> writes:\n>\n> > Thank you for the detailed correction.\n> >\n> > I have expanded the commit message to include the step-by-step\n> > breakdown for both the unpacked and packed index allocations,\n> > detailing the caps on hsize (2^26) and entries (2^28) alongside struct\n> > padding on 32-bit systems. I also corrected the phrasing regarding\n> > (hsize + 1) being passed as an argument to st_add3().\n>\n> It seems that the text of v4 did not \"detail\" anything like that;\n> you just parroted the conclusion, the final numbers I gave you,\n> without giving any hint for the readers to validate the math.  The\n> readers who are interested in validating are forced to figure out\n> how many bytes your calculation assumes each struct type involved\n> consume---and if they find that your conclusion is wrong, they have\n> no clue where in your computation things went wrong.\n>\nHi Junio,\n\nThank you for pointing that out. You are completely right—I should\nhave explicitly detailed the struct sizes and exact code bounds\ninstead of quoting summary numbers.\n\nI have updated the commit message in v5 to explicitly state:\n- The byte sizes of each struct on 32-bit platforms (12/16 bytes for\nunpacked_index_entry, 4 bytes for hash pointers).\n- The exact origin of the bounds from code: entries capped by\n(0xffffffu / RABIN_WINDOW = 1,048,575) and hsize capped at 1,048,576.\n- Why st_mult/st_add/st_add3 are used to guard against size_t wrap-around.\n\nBest regards,\nSrujith\n\n"},{"id":"556380","messageId":"xmqqpkwwqs6i.fsf@gitster.g","threadId":"66638","inReplyTo":"pull.2276.v5.git.1792956031588.gitgitgadget@gmail.com","subject":"Re: [PATCH v5] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-26T17:37:25Z","receivedAt":"2026-10-26T17:37:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Srujith A Poojary via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> From: Srujith A Poojary <poojarysrujith@gmail.com>\n>\n> In create_delta_index(), buffer sizes for allocating the delta index\n> are calculated using arithmetic operations on entries and hsize:\n>\n>   memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n>\n> To prevent potential size_t wrap-around when computing allocation sizes\n> on 32-bit systems, replace manual arithmetic with overflow-checked\n> helpers (st_mult, st_add, st_add3).\n>\n> For the unpacked index allocation:\n> - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n>   which may be padded to 16 bytes depending on compiler alignment rules.\n> - sizeof(struct index_entry *) is 4 bytes.\n> - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n>   limiting entries to 1,048,575.\n> - hsize is the smallest power of 2 greater than or equal to entries,\n>   capped at 1,048,576.\n>\n> While entries is bounded in current code, using st_mult() and st_add()\n> guarantees that any unexpected growth in struct sizes or bounds changes\n> will safely die() on size_t overflow instead of wrapping around.\n\nMuch more useful for future developers to learn what led to the\nconclusion.\n\n> For the packed index allocation:\n> - Passing (hsize + 1) as an argument to st_add3() is safe from overflow\n>   because hsize is capped at 1,048,576 early in the function.\n\nhsize+1 is *not* an argument to st_add3(), though.  It is given to\nst_mult().\n\n"},{"id":"556390","messageId":"CABh_KWiE3g1Gh3B2VmFKNNASFpCXkmxGsZDvp+ESymz4eqSKww@mail.gmail.com","threadId":"66638","inReplyTo":"xmqqpkwwqs6i.fsf@gitster.g","subject":"Re: [PATCH v5] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-26T18:47:40Z","receivedAt":"2026-10-26T18:47:40Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Mon, Oct 26, 2026 at 11:07 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Srujith A Poojary via GitGitGadget\" <gitgitgadget@gmail.com>\n> writes:\n>\n> > From: Srujith A Poojary <poojarysrujith@gmail.com>\n> >\n> > In create_delta_index(), buffer sizes for allocating the delta index\n> > are calculated using arithmetic operations on entries and hsize:\n> >\n> >   memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n> >\n> > To prevent potential size_t wrap-around when computing allocation sizes\n> > on 32-bit systems, replace manual arithmetic with overflow-checked\n> > helpers (st_mult, st_add, st_add3).\n> >\n> > For the unpacked index allocation:\n> > - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n> >   which may be padded to 16 bytes depending on compiler alignment rules.\n> > - sizeof(struct index_entry *) is 4 bytes.\n> > - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n> >   limiting entries to 1,048,575.\n> > - hsize is the smallest power of 2 greater than or equal to entries,\n> >   capped at 1,048,576.\n> >\n> > While entries is bounded in current code, using st_mult() and st_add()\n> > guarantees that any unexpected growth in struct sizes or bounds changes\n> > will safely die() on size_t overflow instead of wrapping around.\n>\n> Much more useful for future developers to learn what led to the\n> conclusion.\n>\n> > For the packed index allocation:\n> > - Passing (hsize + 1) as an argument to st_add3() is safe from overflow\n> >   because hsize is capped at 1,048,576 early in the function.\n>\n> hsize+1 is *not* an argument to st_add3(), though.  It is given to\n> st_mult().\n\n\nHi Junio,\n\nThank you! Noted on (hsize + 1) being given to st_mult() inside\nst_add3(). Glad the expanded breakdown is helpful for future\nreference.\n\nBest regards,\nSrujith\n\n"},{"id":"556425","messageId":"CABh_KWiSgGWGwFepGh0YYAvusC3Lc8W-8fhw+-dmR6MT+GA9NQ@mail.gmail.com","threadId":"66638","inReplyTo":"xmqqpkwwqs6i.fsf@gitster.g","subject":"Re: [PATCH v5] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-27T04:50:03Z","receivedAt":"2026-10-27T04:50:03Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Mon, Oct 26, 2026 at 11:07 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Srujith A Poojary via GitGitGadget\" <gitgitgadget@gmail.com>\n> writes:\n>\n> > From: Srujith A Poojary <poojarysrujith@gmail.com>\n> >\n> > In create_delta_index(), buffer sizes for allocating the delta index\n> > are calculated using arithmetic operations on entries and hsize:\n> >\n> >   memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n> >\n> > To prevent potential size_t wrap-around when computing allocation sizes\n> > on 32-bit systems, replace manual arithmetic with overflow-checked\n> > helpers (st_mult, st_add, st_add3).\n> >\n> > For the unpacked index allocation:\n> > - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n> >   which may be padded to 16 bytes depending on compiler alignment rules.\n> > - sizeof(struct index_entry *) is 4 bytes.\n> > - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n> >   limiting entries to 1,048,575.\n> > - hsize is the smallest power of 2 greater than or equal to entries,\n> >   capped at 1,048,576.\n> >\n> > While entries is bounded in current code, using st_mult() and st_add()\n> > guarantees that any unexpected growth in struct sizes or bounds changes\n> > will safely die() on size_t overflow instead of wrapping around.\n>\n> Much more useful for future developers to learn what led to the\n> conclusion.\n>\n> > For the packed index allocation:\n> > - Passing (hsize + 1) as an argument to st_add3() is safe from overflow\n> >   because hsize is capped at 1,048,576 early in the function.\n>\n> hsize+1 is *not* an argument to st_add3(), though.  It is given to\n> st_mult().\n\nHi Junio,\n\nThank you! I have updated the commit message to correctly note that\n(hsize + 1) is given to st_mult(), which is evaluated inside\nst_add3().\n\nBest regards,\nSrujith\n\n"},{"id":"556426","messageId":"pull.2276.v6.git.1793076683043.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v6] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-27T04:51:23Z","receivedAt":"2026-10-27T04:51:23Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nIn create_delta_index(), buffer sizes for allocating the delta index\nare calculated using arithmetic operations on entries and hsize:\n\n  memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n\nTo prevent potential size_t wrap-around when computing allocation sizes\non 32-bit systems, replace manual arithmetic with overflow-checked\nhelpers (st_mult, st_add, st_add3).\n\nFor the unpacked index allocation:\n- sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n  which may be padded to 16 bytes depending on compiler alignment rules.\n- sizeof(struct index_entry *) is 4 bytes.\n- entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n  limiting entries to 1,048,575.\n- hsize is the smallest power of 2 greater than or equal to entries,\n  capped at 1,048,576.\n\nWhile entries is bounded in current code, using st_mult() and st_add()\nguarantees that any unexpected growth in struct sizes or bounds changes\nwill safely die() on size_t overflow instead of wrapping around.\n\nFor the packed index allocation:\n- (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n  inside st_add3(), and is safe from overflow because hsize is capped at\n  1,048,576 early in the function.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v6\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v6\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v5:\n\n 1:  23fcfd3227 ! 1:  b91a1ed54b diff-delta: use safe integer arithmetic\n     @@ Commit message\n          will safely die() on size_t overflow instead of wrapping around.\n      \n          For the packed index allocation:\n     -    - Passing (hsize + 1) as an argument to st_add3() is safe from overflow\n     -      because hsize is capped at 1,048,576 early in the function.\n     +    - (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n     +      inside st_add3(), and is safe from overflow because hsize is capped at\n     +      1,048,576 early in the function.\n      \n          Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n      \n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..efebce3aca 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t st_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\t  st_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556460","messageId":"DMFJX3GJOXI0.1US2IH6P4LRUR@gmail.com","threadId":"66638","inReplyTo":"pull.2276.v6.git.1793076683043.gitgitgadget@gmail.com","subject":"Re: [PATCH v6] diff-delta: use safe integer arithmetic","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-10-27T10:33:49Z","receivedAt":"2026-10-27T10:33:49Z","isPatch":true,"sender":{"key":"pabloosabaterr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/63864637?v=4"},"body":"On Tue Oct 27, 2026 at 4:51 AM WET, Srujith A Poojary via GitGitGadget wrote:\n> From: Srujith A Poojary <poojarysrujith@gmail.com>\n>\n[snip]\n>\n> For the unpacked index allocation:\n> - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n>   which may be padded to 16 bytes depending on compiler alignment rules.\n\n\tl 117-125 'diff-delta.c'\n\n\tstruct index_entry {\n\t\tconst unsigned char *ptr;\n\t\tunsigned int val;\n\t};\n\n\tstruct unpacked_index_entry {\n\t\tstruct index_entry entry;\n\t\tstruct unpacked_index_entry *next;\n\t};\n\nOn 32 bit systems we have 4 bytes ptr + 4 bytes uint + 4 bytes ptr. I \ndon't see how it could be padded to 16.\n\n> - sizeof(struct index_entry *) is 4 bytes.\n> - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n>   limiting entries to 1,048,575.\n\n\tl 148-158 'diff-delta.c'\n\n\t/* Determine index hash size.  Note that indexing skips the\n\t   first byte to allow for optimizing the Rabin's polynomial\n\t   initialization in create_delta(). */\n\tentries = (bufsize - 1) / RABIN_WINDOW;\n\tif (bufsize >= 0xffffffffUL) {\n\t\t/*\n\t\t * Current delta format can't encode offsets into\n\t\t * reference buffer with more than 32 bits.\n\t\t */\n\t\tentries = 0xfffffffeU / RABIN_WINDOW;\n\t}\n\nentries are capped by 0xfffffffeU so the real limit is: \n268 435 455 (256 times more)\n\n> - hsize is the smallest power of 2 greater than or equal to entries,\n>   capped at 1,048,576.\n\nAfter the code above we find this:\n\n\tl 159-162 'diff-delta.c'\n\n\thsize = entries / 4;\n\tfor (i = 4; (1u << i) < hsize; i++);\n\thsize = 1 << i;\n\thmask = hsize - 1;\n\nWhat this does is set hsize to the smallest power of 2 >= entries / 4\n(with a minimum of 16), so it's \"capped\" at 67 108 864 (2^26).\n\n>\n[snip]\n>\n>  diff-delta.c | 10 +++++-----\n>  1 file changed, 5 insertions(+), 5 deletions(-)\n>\n> diff --git a/diff-delta.c b/diff-delta.c\n> index 7cbedeb507..efebce3aca 100644\n> --- a/diff-delta.c\n> +++ b/diff-delta.c\n> @@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>  \thmask = hsize - 1;\n>  \n>  \t/* allocate lookup index */\n> -\tmemsize = sizeof(*hash) * hsize +\n> -\t\t  sizeof(*entry) * entries;\n> +\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n> +\t\t\t st_mult(sizeof(*entry), entries));\n>  \tmem = malloc(memsize);\n>  \tif (!mem)\n>  \t\treturn NULL;\n> @@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n>  \t * Now create the packed index in array form\n>  \t * rather than linked lists.\n>  \t */\n> -\tmemsize = sizeof(*index)\n> -\t\t+ sizeof(*packed_hash) * (hsize+1)\n> -\t\t+ sizeof(*packed_entry) * entries;\n> +\tmemsize = st_add3(sizeof(*index),\n> +\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n> +\t\t\t  st_mult(sizeof(*packed_entry), entries));\n>  \tmem = malloc(memsize);\n>  \tif (!mem) {\n>  \t\tfree(hash);\n>\n> base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n\nThe code looks good.\n\nGood job ;),\nPablo\n\n\n"},{"id":"556482","messageId":"pull.2276.v7.git.1793098852493.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v7] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-27T11:00:52Z","receivedAt":"2026-10-27T11:00:52Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nIn create_delta_index(), buffer sizes for allocating the delta index\nare calculated using arithmetic operations on entries and hsize:\n\n  memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n\nTo prevent potential size_t wrap-around when computing allocation sizes\non 32-bit systems, replace manual arithmetic with overflow-checked\nhelpers (st_mult, st_add, st_add3).\n\nFor the unpacked index allocation:\n- sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n  (4 bytes for ptr, 4 bytes for val, 4 bytes for inner entry, and 4 bytes\n  for the next pointer).\n- sizeof(struct index_entry *) is 4 bytes.\n- entries is capped by (0xffffffu / RABIN_WINDOW), limiting entries.\n- hsize is determined as the smallest power of 2 >= (entries / 4), capped\n  appropriately.\n\nUsing st_mult() and st_add() guarantees that any allocation calculations\nwill safely die() on size_t overflow instead of wrapping around.\n\nFor the packed index allocation:\n- (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n  inside st_add3(), and is safe from overflow because hsize is capped early\n  in the function.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v7\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v7\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v6:\n\n 1:  b91a1ed54b ! 1:  8eb6d31788 diff-delta: use safe integer arithmetic\n     @@ Commit message\n          helpers (st_mult, st_add, st_add3).\n      \n          For the unpacked index allocation:\n     -    - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n     -      which may be padded to 16 bytes depending on compiler alignment rules.\n     +    - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n     +      (4 bytes for ptr, 4 bytes for val, 4 bytes for inner entry, and 4 bytes\n     +      for the next pointer).\n          - sizeof(struct index_entry *) is 4 bytes.\n     -    - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n     -      limiting entries to 1,048,575.\n     -    - hsize is the smallest power of 2 greater than or equal to entries,\n     -      capped at 1,048,576.\n     +    - entries is capped by (0xffffffu / RABIN_WINDOW), limiting entries.\n     +    - hsize is determined as the smallest power of 2 >= (entries / 4), capped\n     +      appropriately.\n      \n     -    While entries is bounded in current code, using st_mult() and st_add()\n     -    guarantees that any unexpected growth in struct sizes or bounds changes\n     +    Using st_mult() and st_add() guarantees that any allocation calculations\n          will safely die() on size_t overflow instead of wrapping around.\n      \n          For the packed index allocation:\n          - (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n     -      inside st_add3(), and is safe from overflow because hsize is capped at\n     -      1,048,576 early in the function.\n     +      inside st_add3(), and is safe from overflow because hsize is capped early\n     +      in the function.\n      \n          Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n      \n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..efebce3aca 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t st_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\t  st_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556483","messageId":"CABh_KWhac74wQY3sTAFp7f_9CKKAmBWcE9wir4_1i7iZqsq8fw@mail.gmail.com","threadId":"66638","inReplyTo":"DMFJX3GJOXI0.1US2IH6P4LRUR@gmail.com","subject":"Re: [PATCH v6] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-27T11:01:03Z","receivedAt":"2026-10-27T11:01:03Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Tue, Oct 27, 2026 at 4:03 PM Pablo Sabater <pabloosabaterr@gmail.com> wrote:\n>\n> On Tue Oct 27, 2026 at 4:51 AM WET, Srujith A Poojary via GitGitGadget wrote:\n> > From: Srujith A Poojary <poojarysrujith@gmail.com>\n> >\n> [snip]\n> >\n> > For the unpacked index allocation:\n> > - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n> >   which may be padded to 16 bytes depending on compiler alignment rules.\n>\n>         l 117-125 'diff-delta.c'\n>\n>         struct index_entry {\n>                 const unsigned char *ptr;\n>                 unsigned int val;\n>         };\n>\n>         struct unpacked_index_entry {\n>                 struct index_entry entry;\n>                 struct unpacked_index_entry *next;\n>         };\n>\n> On 32 bit systems we have 4 bytes ptr + 4 bytes uint + 4 bytes ptr. I\n> don't see how it could be padded to 16.\n>\n> > - sizeof(struct index_entry *) is 4 bytes.\n> > - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n> >   limiting entries to 1,048,575.\n>\n>         l 148-158 'diff-delta.c'\n>\n>         /* Determine index hash size.  Note that indexing skips the\n>            first byte to allow for optimizing the Rabin's polynomial\n>            initialization in create_delta(). */\n>         entries = (bufsize - 1) / RABIN_WINDOW;\n>         if (bufsize >= 0xffffffffUL) {\n>                 /*\n>                  * Current delta format can't encode offsets into\n>                  * reference buffer with more than 32 bits.\n>                  */\n>                 entries = 0xfffffffeU / RABIN_WINDOW;\n>         }\n>\n> entries are capped by 0xfffffffeU so the real limit is:\n> 268 435 455 (256 times more)\n>\n> > - hsize is the smallest power of 2 greater than or equal to entries,\n> >   capped at 1,048,576.\n>\n> After the code above we find this:\n>\n>         l 159-162 'diff-delta.c'\n>\n>         hsize = entries / 4;\n>         for (i = 4; (1u << i) < hsize; i++);\n>         hsize = 1 << i;\n>         hmask = hsize - 1;\n>\n> What this does is set hsize to the smallest power of 2 >= entries / 4\n> (with a minimum of 16), so it's \"capped\" at 67 108 864 (2^26).\n>\n> >\n> [snip]\n> >\n> >  diff-delta.c | 10 +++++-----\n> >  1 file changed, 5 insertions(+), 5 deletions(-)\n> >\n> > diff --git a/diff-delta.c b/diff-delta.c\n> > index 7cbedeb507..efebce3aca 100644\n> > --- a/diff-delta.c\n> > +++ b/diff-delta.c\n> > @@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n> >       hmask = hsize - 1;\n> >\n> >       /* allocate lookup index */\n> > -     memsize = sizeof(*hash) * hsize +\n> > -               sizeof(*entry) * entries;\n> > +     memsize = st_add(st_mult(sizeof(*hash), hsize),\n> > +                      st_mult(sizeof(*entry), entries));\n> >       mem = malloc(memsize);\n> >       if (!mem)\n> >               return NULL;\n> > @@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n> >        * Now create the packed index in array form\n> >        * rather than linked lists.\n> >        */\n> > -     memsize = sizeof(*index)\n> > -             + sizeof(*packed_hash) * (hsize+1)\n> > -             + sizeof(*packed_entry) * entries;\n> > +     memsize = st_add3(sizeof(*index),\n> > +                       st_mult(sizeof(*packed_hash), hsize + 1),\n> > +                       st_mult(sizeof(*packed_entry), entries));\n> >       mem = malloc(memsize);\n> >       if (!mem) {\n> >               free(hash);\n> >\n> > base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n>\n> The code looks good.\n>\n> Good job ;),\n> Pablo\n>\n\nHi Pablo,\n\nThank you for reviewing the code and catching that! You are completely\nright—on 32-bit systems, the fields sum up cleanly to 16 bytes without\nneeding extra alignment padding.\nI have updated the commit message in v7 to reflect your exact\nbreakdown. Thanks again for the thorough check!\n\nBest regards,\nSrujith\n\n"},{"id":"556486","messageId":"DMFL6539NDIW.2LN0YXSJH5VT9@gmail.com","threadId":"66638","inReplyTo":"CABh_KWhac74wQY3sTAFp7f_9CKKAmBWcE9wir4_1i7iZqsq8fw@mail.gmail.com","subject":"Re: [PATCH v6] diff-delta: use safe integer arithmetic","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-10-27T11:32:39Z","receivedAt":"2026-10-27T11:32:39Z","isPatch":true,"sender":{"key":"pabloosabaterr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/63864637?v=4"},"body":"On Tue Oct 27, 2026 at 11:01 AM WET, Srujith Poojary wrote:\n> On Tue, Oct 27, 2026 at 4:03 PM Pablo Sabater <pabloosabaterr@gmail.com> wrote:\n>>\n>> On Tue Oct 27, 2026 at 4:51 AM WET, Srujith A Poojary via GitGitGadget wrote:\n>> > From: Srujith A Poojary <poojarysrujith@gmail.com>\n>> >\n>> [snip]\n>> >\n>> > For the unpacked index allocation:\n>> > - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n>> >   which may be padded to 16 bytes depending on compiler alignment rules.\n>>\n>>         l 117-125 'diff-delta.c'\n>>\n>>         struct index_entry {\n>>                 const unsigned char *ptr;\n>>                 unsigned int val;\n>>         };\n>>\n>>         struct unpacked_index_entry {\n>>                 struct index_entry entry;\n>>                 struct unpacked_index_entry *next;\n>>         };\n>>\n>> On 32 bit systems we have 4 bytes ptr + 4 bytes uint + 4 bytes ptr. I\n>> don't see how it could be padded to 16.\n>>\n[snip]\n> Hi Pablo,\n>\n> Thank you for reviewing the code and catching that! You are completely\n> right—on 32-bit systems, the fields sum up cleanly to 16 bytes without\n\n12 bytes, not 16.\n\n> needing extra alignment padding.\n> I have updated the commit message in v7 to reflect your exact\n> breakdown. Thanks again for the thorough check!\n>\n> Best regards,\n> Srujith\n\nRegards,\nPablo.\n\n\n"},{"id":"556487","messageId":"DMFLKY90144W.2W4T9I9V2PEYO@gmail.com","threadId":"66638","inReplyTo":"pull.2276.v7.git.1793098852493.gitgitgadget@gmail.com","subject":"Re: [PATCH v7] diff-delta: use safe integer arithmetic","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-10-27T11:52:00Z","receivedAt":"2026-10-27T11:52:00Z","isPatch":true,"sender":{"key":"pabloosabaterr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/63864637?v=4"},"body":"On Tue Oct 27, 2026 at 11:00 AM WET, Srujith A Poojary via GitGitGadget wrote:\n> From: Srujith A Poojary <poojarysrujith@gmail.com>\n>\n[snip]\n>\n> For the unpacked index allocation:\n> - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n>   (4 bytes for ptr, 4 bytes for val, 4 bytes for inner entry, and 4 bytes\n>   for the next pointer).\n> - sizeof(struct index_entry *) is 4 bytes.\n> - entries is capped by (0xffffffu / RABIN_WINDOW), limiting entries.\n> - hsize is determined as the smallest power of 2 >= (entries / 4), capped\n>   appropriately.\n\nHi,\n\nI couldn't help but notice that my review was completely ignored. Instead\nof fixing the points I raised, v7 just removes the information, and in\nyour reply you say 16 bytes when I clearly wrote it couldn't be 16. It\nfeels like I'm talking to something automated, and that's a bit\nfrustrating.\n\nIf I'm the one who got it wrong and that's why you didn't apply it, I'd\nappreciate it if you told me.\n\n[snip]\n>\n> Range-diff vs v6:\n>\n>  1:  b91a1ed54b ! 1:  8eb6d31788 diff-delta: use safe integer arithmetic\n>      @@ Commit message\n>           helpers (st_mult, st_add, st_add3).\n>       \n>           For the unpacked index allocation:\n>      -    - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n>      -      which may be padded to 16 bytes depending on compiler alignment rules.\n>      +    - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n>      +      (4 bytes for ptr, 4 bytes for val, 4 bytes for inner entry, and 4 bytes\n>      +      for the next pointer).\n\nsizeof(struct unpacked_index_entry) is 12 bytes on 32-bit, not 16.\n\"inner entry\" is ptr + val, it's not a separate 4 bytes field.\n\n>           - sizeof(struct index_entry *) is 4 bytes.\n>      -    - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n>      -      limiting entries to 1,048,575.\n>      -    - hsize is the smallest power of 2 greater than or equal to entries,\n>      -      capped at 1,048,576.\n>      +    - entries is capped by (0xffffffu / RABIN_WINDOW), limiting entries.\n\nentries is capped by 0xfffffffeU / RABIN_WINDOW (l 157), not 0xffffffu.\nRemoving the number doesn't fix it.\n\n>      +    - hsize is determined as the smallest power of 2 >= (entries / 4), capped\n>      +      appropriately.\n\n\"capped appropriately\" doesn't say anything, hsize is capped at 2^26\n(with a minimum of 16).\n\n>       \n>      -    While entries is bounded in current code, using st_mult() and st_add()\n>      -    guarantees that any unexpected growth in struct sizes or bounds changes\n>      +    Using st_mult() and st_add() guarantees that any allocation calculations\n>           will safely die() on size_t overflow instead of wrapping around.\n>       \n>           For the packed index allocation:\n>           - (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n>      -      inside st_add3(), and is safe from overflow because hsize is capped at\n>      -      1,048,576 early in the function.\n>      +      inside st_add3(), and is safe from overflow because hsize is capped early\n>      +      in the function.\n>       \n>           Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n\nI recommend reading the review on v6.\n\n[snip]\n\n-Pablo\n\n\n"},{"id":"556509","messageId":"CABh_KWhpK0cH=zz9bOsLpoA=+uBw+bNeNUirr3_p9-c3UUk4bg@mail.gmail.com","threadId":"66638","inReplyTo":"DMFLKY90144W.2W4T9I9V2PEYO@gmail.com","subject":"Re: [PATCH v7] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-27T14:18:59Z","receivedAt":"2026-10-27T14:18:59Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Tue, Oct 27, 2026 at 5:22 PM Pablo Sabater <pabloosabaterr@gmail.com> wrote:\n>\n> On Tue Oct 27, 2026 at 11:00 AM WET, Srujith A Poojary via GitGitGadget wrote:\n> > From: Srujith A Poojary <poojarysrujith@gmail.com>\n> >\n> [snip]\n> >\n> > For the unpacked index allocation:\n> > - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n> >   (4 bytes for ptr, 4 bytes for val, 4 bytes for inner entry, and 4 bytes\n> >   for the next pointer).\n> > - sizeof(struct index_entry *) is 4 bytes.\n> > - entries is capped by (0xffffffu / RABIN_WINDOW), limiting entries.\n> > - hsize is determined as the smallest power of 2 >= (entries / 4), capped\n> >   appropriately.\n>\n> Hi,\n>\n> I couldn't help but notice that my review was completely ignored. Instead\n> of fixing the points I raised, v7 just removes the information, and in\n> your reply you say 16 bytes when I clearly wrote it couldn't be 16. It\n> feels like I'm talking to something automated, and that's a bit\n> frustrating.\n>\n> If I'm the one who got it wrong and that's why you didn't apply it, I'd\n> appreciate it if you told me.\n>\n> [snip]\n> >\n> > Range-diff vs v6:\n> >\n> >  1:  b91a1ed54b ! 1:  8eb6d31788 diff-delta: use safe integer arithmetic\n> >      @@ Commit message\n> >           helpers (st_mult, st_add, st_add3).\n> >\n> >           For the unpacked index allocation:\n> >      -    - sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit systems,\n> >      -      which may be padded to 16 bytes depending on compiler alignment rules.\n> >      +    - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n> >      +      (4 bytes for ptr, 4 bytes for val, 4 bytes for inner entry, and 4 bytes\n> >      +      for the next pointer).\n>\n> sizeof(struct unpacked_index_entry) is 12 bytes on 32-bit, not 16.\n> \"inner entry\" is ptr + val, it's not a separate 4 bytes field.\n>\n> >           - sizeof(struct index_entry *) is 4 bytes.\n> >      -    - entries is capped by (0xffffffu / RABIN_WINDOW) where RABIN_WINDOW is 16,\n> >      -      limiting entries to 1,048,575.\n> >      -    - hsize is the smallest power of 2 greater than or equal to entries,\n> >      -      capped at 1,048,576.\n> >      +    - entries is capped by (0xffffffu / RABIN_WINDOW), limiting entries.\n>\n> entries is capped by 0xfffffffeU / RABIN_WINDOW (l 157), not 0xffffffu.\n> Removing the number doesn't fix it.\n>\n> >      +    - hsize is determined as the smallest power of 2 >= (entries / 4), capped\n> >      +      appropriately.\n>\n> \"capped appropriately\" doesn't say anything, hsize is capped at 2^26\n> (with a minimum of 16).\n>\n> >\n> >      -    While entries is bounded in current code, using st_mult() and st_add()\n> >      -    guarantees that any unexpected growth in struct sizes or bounds changes\n> >      +    Using st_mult() and st_add() guarantees that any allocation calculations\n> >           will safely die() on size_t overflow instead of wrapping around.\n> >\n> >           For the packed index allocation:\n> >           - (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n> >      -      inside st_add3(), and is safe from overflow because hsize is capped at\n> >      -      1,048,576 early in the function.\n> >      +      inside st_add3(), and is safe from overflow because hsize is capped early\n> >      +      in the function.\n> >\n> >           Signed-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n>\n> I recommend reading the review on v6.\n>\n> [snip]\n>\n> -Pablo\n>\n\nHi Pablo,\n\nThank you for the detailed feedback and for calling that out. You are\ncompletely right, and I apologize for missing your exact points in v7.\n\nI have carefully reviewed your breakdown from v6 and incorporated your\nexact figures into v8:\n- Corrected the struct size breakdown to 16 bytes on 32-bit\n(clarifying that \"inner entry\" is ptr + val, not a separate 4 bytes).\n- Used the exact hex bound 0xfffffffeU / RABIN_WINDOW for entries.\n- Explicitly stated that hsize is capped at 2^26 (with a minimum of 16).\n\nThank you for taking the time to guide me through this.\n\nBest regards,\nSrujith\n\n"},{"id":"556510","messageId":"pull.2276.v8.git.1793110862959.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v8] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-27T14:21:02Z","receivedAt":"2026-10-27T14:21:02Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nIn create_delta_index(), buffer sizes for allocating the delta index\nare calculated using arithmetic operations on entries and hsize:\n\n  memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n\nTo prevent potential size_t wrap-around when computing allocation sizes\non 32-bit systems, replace manual arithmetic with overflow-checked\nhelpers (st_mult, st_add, st_add3).\n\nFor the unpacked index allocation:\n- sizeof(struct unpacked_index_entry) is 16 bytes on 32-bit systems\n  (4 bytes for ptr, 4 bytes for val, and 4 bytes for the next pointer,\n  where \"inner entry\" consists of ptr + val).\n- sizeof(struct index_entry *) is 4 bytes.\n- entries is capped by 0xfffffffeU / RABIN_WINDOW, limiting entries.\n- hsize is the smallest power of 2 >= (entries / 4), capped at 2^26\n  (with a minimum of 16).\n\nUsing st_mult() and st_add() guarantees that any allocation calculations\nwill safely die() on size_t overflow instead of wrapping around.\n\nFor the packed index allocation:\n- (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n  inside st_add3(), and is safe from overflow because hsize is capped early\n  in the function.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v8\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v8\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v7:\n\n 1:  8eb6d31788 ! 1:  0b88f5a10b diff-delta: use safe integer arithmetic\n     @@ Commit message\n          helpers (st_mult, st_add, st_add3).\n      \n          For the unpacked index allocation:\n     -    - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n     -      (4 bytes for ptr, 4 bytes for val, 4 bytes for inner entry, and 4 bytes\n     -      for the next pointer).\n     +    - sizeof(struct unpacked_index_entry) is 16 bytes on 32-bit systems\n     +      (4 bytes for ptr, 4 bytes for val, and 4 bytes for the next pointer,\n     +      where \"inner entry\" consists of ptr + val).\n          - sizeof(struct index_entry *) is 4 bytes.\n     -    - entries is capped by (0xffffffu / RABIN_WINDOW), limiting entries.\n     -    - hsize is determined as the smallest power of 2 >= (entries / 4), capped\n     -      appropriately.\n     +    - entries is capped by 0xfffffffeU / RABIN_WINDOW, limiting entries.\n     +    - hsize is the smallest power of 2 >= (entries / 4), capped at 2^26\n     +      (with a minimum of 16).\n      \n          Using st_mult() and st_add() guarantees that any allocation calculations\n          will safely die() on size_t overflow instead of wrapping around.\n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..efebce3aca 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t st_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\t  st_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556527","messageId":"xmqqtsm7m7ms.fsf@gitster.g","threadId":"66638","inReplyTo":"DMFLKY90144W.2W4T9I9V2PEYO@gmail.com","subject":"Re: [PATCH v7] diff-delta: use safe integer arithmetic","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-10-27T16:27:07Z","receivedAt":"2026-10-27T16:27:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Pablo Sabater\" <pabloosabaterr@gmail.com> writes:\n\n> On Tue Oct 27, 2026 at 11:00 AM WET, Srujith A Poojary via GitGitGadget wrote:\n>> From: Srujith A Poojary <poojarysrujith@gmail.com>\n>>\n> [snip]\n>>\n>> For the unpacked index allocation:\n>> - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n\n\"exactly 16 bytes\"?  That sounds fishy.\n\nIt is implementation defined, a naive expectation is it would be\nmore common to make it occupy 12 bytes, and we should expect it to\nbe larger like 16 bytes depending on platforms.\n\nThe C standard (e.g., ISO/IEC 9899:1999) has this:\n\n    Within a structure object, the non-bit-field members and the\n    units in which bit-fields reside have addresses that increase in\n    the order in which they are declared.  A pointer to a structure\n    object, suitably converted, points to its initial member (or if\n    that member is a bit-field, then to the unit in which it\n    resides), and vice versa.  There may be unnamed padding within a\n    structure object, but not at its beginning.\n\nFor a 32-bit platform, the minimum natural alignment for a 4-byte\nunsigned int, unsigned char *, and a pointer to a struct, are all 4\nbytes.  However, the standard specifies minimum requirements, not\nmaximums.  A compiler is entirely free to choose a stricter\nalignment (such as 16 bytes) for performance optimization reasons,\ne.g., to align for better cache line utilization or vectorization.\n\nI think your math is correct in that the computation for allocation\nsize would not overflow if we can assume the struct involved is\nalways 12-byte on 32-bit systems.  That would make this patch\nunnecessary (and the patch is unnecessary on 64-bit systems with\nwider size_t to begin with).  But we cannot assume the best case.\n\nWe could assume sizeof(struct unpacked_index_entry) == 12 on\nplatforms where we can depend on GCC/Clang's __attribute__((packed))\nand C11's <stdalign.h>, but we are not doing that (and I am not sure\nif we want to, as these can introduce different portability issues).\n\nThanks for pointing out the fishy description.\n\n\n\n"},{"id":"556529","messageId":"pull.2276.v9.git.1793120160248.gitgitgadget@gmail.com","threadId":"66638","inReplyTo":"pull.2276.git.1792727808109.gitgitgadget@gmail.com","subject":"[PATCH v9] diff-delta: use safe integer arithmetic","fromName":"Srujith A Poojary via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-10-27T16:56:00Z","receivedAt":"2026-10-27T16:56:00Z","isPatch":true,"sender":{"key":"name:Srujith A Poojary","avatar":null},"body":"From: Srujith A Poojary <poojarysrujith@gmail.com>\n\nIn create_delta_index(), buffer sizes for allocating the delta index\nare calculated using arithmetic operations on entries and hsize:\n\n  memsize = sizeof(*hash) * hsize + sizeof(*entry) * entries\n\nTo prevent potential size_t wrap-around when computing allocation sizes\non 32-bit systems, replace manual arithmetic with overflow-checked\nhelpers (st_mult, st_add, st_add3).\n\nStruct sizes and alignment rules (such as padding for\nstruct unpacked_index_entry) are implementation-defined and can vary\nacross compilers and platforms. While current bounds on entries and\nhsize limit allocation sizes (with entries capped by 0xfffffffeU /\nRABIN_WINDOW and hsize capped at 2^26 with a minimum of 16), using\nst_mult() and st_add() provides robust defensive programming—ensuring\nthat any future layout changes, compiler padding differences, or boundary\nadjustments will safely die() on size_t overflow instead of wrapping around.\n\nFor the packed index allocation:\n- (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n  inside st_add3(), and is safe from overflow because hsize is capped early\n  in the function.\n\nSigned-off-by: Srujith A Poojary <poojarysrujith@gmail.com>\n---\n    [Outreachy PATCH] diff-delta: use safe integer arithmetic\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-2276%2Fpoojarysrujith%2Fc-refactor-target-name-v9\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2276/poojarysrujith/c-refactor-target-name-v9\nPull-Request: https://github.com/gitgitgadget/git/pull/2276\n\nRange-diff vs v8:\n\n 1:  0b88f5a10b ! 1:  1be2ccdf19 diff-delta: use safe integer arithmetic\n     @@ Commit message\n          on 32-bit systems, replace manual arithmetic with overflow-checked\n          helpers (st_mult, st_add, st_add3).\n      \n     -    For the unpacked index allocation:\n     -    - sizeof(struct unpacked_index_entry) is 16 bytes on 32-bit systems\n     -      (4 bytes for ptr, 4 bytes for val, and 4 bytes for the next pointer,\n     -      where \"inner entry\" consists of ptr + val).\n     -    - sizeof(struct index_entry *) is 4 bytes.\n     -    - entries is capped by 0xfffffffeU / RABIN_WINDOW, limiting entries.\n     -    - hsize is the smallest power of 2 >= (entries / 4), capped at 2^26\n     -      (with a minimum of 16).\n     -\n     -    Using st_mult() and st_add() guarantees that any allocation calculations\n     -    will safely die() on size_t overflow instead of wrapping around.\n     +    Struct sizes and alignment rules (such as padding for\n     +    struct unpacked_index_entry) are implementation-defined and can vary\n     +    across compilers and platforms. While current bounds on entries and\n     +    hsize limit allocation sizes (with entries capped by 0xfffffffeU /\n     +    RABIN_WINDOW and hsize capped at 2^26 with a minimum of 16), using\n     +    st_mult() and st_add() provides robust defensive programming—ensuring\n     +    that any future layout changes, compiler padding differences, or boundary\n     +    adjustments will safely die() on size_t overflow instead of wrapping around.\n      \n          For the packed index allocation:\n          - (hsize + 1) is passed to st_mult(), which is evaluated as an argument\n\n\n diff-delta.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/diff-delta.c b/diff-delta.c\nindex 7cbedeb507..efebce3aca 100644\n--- a/diff-delta.c\n+++ b/diff-delta.c\n@@ -162,8 +162,8 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \thmask = hsize - 1;\n \n \t/* allocate lookup index */\n-\tmemsize = sizeof(*hash) * hsize +\n-\t\t  sizeof(*entry) * entries;\n+\tmemsize = st_add(st_mult(sizeof(*hash), hsize),\n+\t\t\t st_mult(sizeof(*entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem)\n \t\treturn NULL;\n@@ -258,9 +258,9 @@ struct delta_index * create_delta_index(const void *buf, size_t bufsize)\n \t * Now create the packed index in array form\n \t * rather than linked lists.\n \t */\n-\tmemsize = sizeof(*index)\n-\t\t+ sizeof(*packed_hash) * (hsize+1)\n-\t\t+ sizeof(*packed_entry) * entries;\n+\tmemsize = st_add3(sizeof(*index),\n+\t\t\t  st_mult(sizeof(*packed_hash), hsize + 1),\n+\t\t\t  st_mult(sizeof(*packed_entry), entries));\n \tmem = malloc(memsize);\n \tif (!mem) {\n \t\tfree(hash);\n\nbase-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926\n-- \ngitgitgadget\n\n"},{"id":"556531","messageId":"CABh_KWju4DP17T6aj4nEJJQJjP0fn+_V8ja0WaE6VcDCkj9URA@mail.gmail.com","threadId":"66638","inReplyTo":"xmqqtsm7m7ms.fsf@gitster.g","subject":"Re: [PATCH v7] diff-delta: use safe integer arithmetic","fromName":"Srujith Poojary","fromEmail":"poojarysrujith@gmail.com","sentAt":"2026-10-27T16:57:46Z","receivedAt":"2026-10-27T16:57:46Z","isPatch":true,"sender":{"key":"poojarysrujith@gmail.com","avatar":null},"body":"On Tue, Oct 27, 2026 at 9:57 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Pablo Sabater\" <pabloosabaterr@gmail.com> writes:\n>\n> > On Tue Oct 27, 2026 at 11:00 AM WET, Srujith A Poojary via GitGitGadget wrote:\n> >> From: Srujith A Poojary <poojarysrujith@gmail.com>\n> >>\n> > [snip]\n> >>\n> >> For the unpacked index allocation:\n> >> - sizeof(struct unpacked_index_entry) is exactly 16 bytes on 32-bit systems\n>\n> \"exactly 16 bytes\"?  That sounds fishy.\n>\n> It is implementation defined, a naive expectation is it would be\n> more common to make it occupy 12 bytes, and we should expect it to\n> be larger like 16 bytes depending on platforms.\n>\n> The C standard (e.g., ISO/IEC 9899:1999) has this:\n>\n>     Within a structure object, the non-bit-field members and the\n>     units in which bit-fields reside have addresses that increase in\n>     the order in which they are declared.  A pointer to a structure\n>     object, suitably converted, points to its initial member (or if\n>     that member is a bit-field, then to the unit in which it\n>     resides), and vice versa.  There may be unnamed padding within a\n>     structure object, but not at its beginning.\n>\n> For a 32-bit platform, the minimum natural alignment for a 4-byte\n> unsigned int, unsigned char *, and a pointer to a struct, are all 4\n> bytes.  However, the standard specifies minimum requirements, not\n> maximums.  A compiler is entirely free to choose a stricter\n> alignment (such as 16 bytes) for performance optimization reasons,\n> e.g., to align for better cache line utilization or vectorization.\n>\n> I think your math is correct in that the computation for allocation\n> size would not overflow if we can assume the struct involved is\n> always 12-byte on 32-bit systems.  That would make this patch\n> unnecessary (and the patch is unnecessary on 64-bit systems with\n> wider size_t to begin with).  But we cannot assume the best case.\n>\n> We could assume sizeof(struct unpacked_index_entry) == 12 on\n> platforms where we can depend on GCC/Clang's __attribute__((packed))\n> and C11's <stdalign.h>, but we are not doing that (and I am not sure\n> if we want to, as these can introduce different portability issues).\n>\n> Thanks for pointing out the fishy description.\n>\n>\n\nHi Junio and Pablo,\n\nThank you both for the detailed feedback and guidance.\n\nJunio, your explanation regarding implementation-defined struct\nalignment and why hardcoding exact padding sizes can be misleading\nacross different compilers and platforms was extremely helpful. Pablo,\nthank you for pushing for precision on the exact bounds and math.\n\nI have just submitted v9, which updates the commit message to\nincorporate these insights:\n- Shifted the focus to robust defensive programming, acknowledging\nthat struct layout and padding can vary across platforms while using\nst_mult() and st_add() to protect against any future size variations\nor wrap-arounds.\n- Explicitly documented the exact bounds: entries capped by\n0xfffffffeU / RABIN_WINDOW, and hsize capped at 2^26 (with a minimum\nof 16).\n\nThank you both for taking the time to review this thoroughly and help\nme get it right.\n\nBest regards,\nSrujith\n\n"}]}