Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #393805 > unrolled thread

Memory protection between compilation units?

Started byMateusz Viste <mateusz@x.invalid>
First post2025-06-11 15:32 +0200
Last post2025-06-21 15:49 -0500
Articles 18 on this page of 58 — 21 participants

Back to article view | Back to comp.lang.c


Contents

  Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-11 15:32 +0200
    Re: Memory protection between compilation units? Josef Möllers <josef@invalid.invalid> - 2025-06-11 16:06 +0200
      Re: Memory protection between compilation units? scott@slp53.sl.home (Scott Lurndal) - 2025-06-11 14:32 +0000
        Re: Memory protection between compilation units? Michael S <already5chosen@yahoo.com> - 2025-06-12 20:01 +0300
          Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-13 09:13 +0200
        Re: Memory protection between compilation units? Richard Heathfield <rjh@cpax.org.uk> - 2025-06-12 19:15 +0100
          Re: Memory protection between compilation units? Rosario19 <Ros@invalid.invalid> - 2025-06-16 18:14 +0200
            Re: Memory protection between compilation units? Richard Heathfield <rjh@cpax.org.uk> - 2025-06-16 17:53 +0100
    Re: Memory protection between compilation units? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2025-06-11 14:30 +0000
    Re: Memory protection between compilation units? David Brown <david.brown@hesbynett.no> - 2025-06-11 17:14 +0200
      Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-12 14:31 +0200
        Re: Memory protection between compilation units? David Brown <david.brown@hesbynett.no> - 2025-06-12 15:29 +0200
          Re: Memory protection between compilation units? scott@slp53.sl.home (Scott Lurndal) - 2025-06-12 14:27 +0000
    Re: Memory protection between compilation units? Opus <ifonly@youknew.org> - 2025-06-11 17:19 +0200
      Re: Memory protection between compilation units? wij <wyniijj5@gmail.com> - 2025-06-11 23:38 +0800
      Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-12 14:41 +0200
        Re: Memory protection between compilation units? scott@slp53.sl.home (Scott Lurndal) - 2025-06-12 13:21 +0000
    Re: Memory protection between compilation units? Kaz Kylheku <643-408-1753@kylheku.com> - 2025-06-11 15:36 +0000
    Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-12 10:28 +0200
      Re: Memory protection between compilation units? scott@slp53.sl.home (Scott Lurndal) - 2025-06-12 13:18 +0000
      Re: Memory protection between compilation units? Kaz Kylheku <643-408-1753@kylheku.com> - 2025-06-12 18:59 +0000
        Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-13 08:42 +0200
          Re: Memory protection between compilation units? Kaz Kylheku <643-408-1753@kylheku.com> - 2025-06-13 16:17 +0000
        Re: Memory protection between compilation units? pozz <pozzugno@gmail.com> - 2025-06-13 09:21 +0200
          Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-13 14:14 +0200
            Re: Memory protection between compilation units? Michael S <already5chosen@yahoo.com> - 2025-06-13 16:56 +0300
              Re: Memory protection between compilation units? Richard Heathfield <rjh@cpax.org.uk> - 2025-06-13 15:43 +0100
                Re: Memory protection between compilation units? Michael S <already5chosen@yahoo.com> - 2025-06-14 22:07 +0300
              Re: Memory protection between compilation units? Kaz Kylheku <643-408-1753@kylheku.com> - 2025-06-13 17:14 +0000
              Re: Memory protection between compilation units? Mateusz Viste <mateusz@not.gonna.tell> - 2025-06-14 21:37 +0000
                Re: Memory protection between compilation units? antispam@fricas.org (Waldek Hebisch) - 2025-06-15 13:57 +0000
                  Re: Memory protection between compilation units? Mateusz Viste <mateusz@not.gonna.tell> - 2025-06-15 20:27 +0000
                    Re: Memory protection between compilation units? antispam@fricas.org (Waldek Hebisch) - 2025-06-15 23:50 +0000
                      Re: Memory protection between compilation units? Kaz Kylheku <643-408-1753@kylheku.com> - 2025-06-16 01:01 +0000
                        Re: Memory protection between compilation units? antispam@fricas.org (Waldek Hebisch) - 2025-06-16 10:00 +0000
                          Re: Memory protection between compilation units? James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-06-16 06:12 -0400
                      Re: Memory protection between compilation units? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-06-16 06:10 -0700
                        Re: Memory protection between compilation units? antispam@fricas.org (Waldek Hebisch) - 2025-06-16 16:47 +0000
            Re: Memory protection between compilation units? Kaz Kylheku <643-408-1753@kylheku.com> - 2025-06-13 16:23 +0000
            Re: Memory protection between compilation units? wij <wyniijj5@gmail.com> - 2025-06-14 02:10 +0800
    Re: Memory protection between compilation units? Mikko <mikko.levanto@iki.fi> - 2025-06-12 11:40 +0300
      Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-12 11:05 +0200
    Re: Memory protection between compilation units? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-06-12 06:05 -0700
      Re: Memory protection between compilation units? Bonita Montero <Bonita.Montero@gmail.com> - 2025-06-13 08:03 +0200
        Re: Memory protection between compilation units? wij <wyniijj5@gmail.com> - 2025-06-14 02:16 +0800
          Re: Memory protection between compilation units? Bonita Montero <Bonita.Montero@gmail.com> - 2025-06-13 20:43 +0200
          Re: Memory protection between compilation units? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-06-13 12:32 -0700
            Re: Memory protection between compilation units? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-06-13 15:48 -0700
      Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-13 08:59 +0200
        Re: Memory protection between compilation units? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-06-13 16:31 -0700
          Re: Memory protection between compilation units? Mateusz Viste <mateusz@not.gonna.tell> - 2025-06-14 22:22 +0000
            Re: Memory protection between compilation units? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-07-01 09:54 -0700
    Re: Memory protection between compilation units? Bonita Montero <Bonita.Montero@gmail.com> - 2025-06-13 08:00 +0200
      Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-13 08:47 +0200
        Re: Memory protection between compilation units? Kaz Kylheku <643-408-1753@kylheku.com> - 2025-06-13 16:19 +0000
    Re: Memory protection between compilation units? Louis Krupp <lkrupp@invalid.pssw.com.invalid> - 2025-06-16 06:29 -0600
      Re: Memory protection between compilation units? Mateusz Viste <mateusz@x.invalid> - 2025-06-16 15:01 +0200
    Re: Memory protection between compilation units? olcott <polcott333@gmail.com> - 2025-06-21 15:49 -0500

Page 3 of 3 — ← Prev page 1 2 [3]


#393821

FromMikko <mikko.levanto@iki.fi>
Date2025-06-12 11:40 +0300
Message-ID<102e3pk$2j4ts$1@dont-email.me>
In reply to#393805
On 2025-06-11 13:32:39 +0000, Mateusz Viste said:

> This might not be a strictly C question, but it definitely concerns all
> C programmers.
> 
> Earlier today, I fixed an out-of-bounds write bug. An obvious issue:
> 
>   static int *socks[0xffff];
> 
>   void update_my_socks(int *sock, int val) {
>     socks[val & 0xffff] = sock;
>   }
> 
> While the presented issue is common knowledge for anyone familiar with
> C, *locating* the bug was challenging. The program did not crash at the
> moment of the out-of-bounds write but much later - somewhere entirely
> different, in a different object file that maintained a static pointer
> for tracking a position in a linked list. To my surprise, the pointer
> was randomly reset to NULL about once a week, causing a segfault.
> Tracing this back to an unrelated out-of-bounds write elsewhere in the
> code was tedious, to say the least.
> 
> This raises a question: how can such corruptions be detected sooner?
> Protected mode prevents interference between programs but doesn’t
> safeguard a program from corrupting itself. Is there a way to enforce
> memory protection between module files of the same program? After all,
> static objects shouldn't be accessible outside their compilation unit.
> 
> How would you approach this?

The traditional method to ensure that a program or a part of a program
does not do what it must not do is testing. In this case the tester
must modify the code so that the array socks is a part of a larger
data structure and and call update_my_socks with different values for
val, including the critical values -1, 0, 0xfffe, and 0xffff.

-- 
Mikko

[toc] | [prev] | [next] | [standalone]


#393822

FromMateusz Viste <mateusz@x.invalid>
Date2025-06-12 11:05 +0200
Message-ID<20250612110502.48dba8b0@mateusz>
In reply to#393821
On Thu, 12 Jun 2025 11:40 Mikko wrote:
> The traditional method to ensure that a program or a part of a program
> does not do what it must not do is testing. In this case the tester
> must modify the code so that the array socks is a part of a larger
> data structure and and call update_my_socks with different values for
> val, including the critical values -1, 0, 0xfffe, and 0xffff.

Essentially checking for out-of-bounds writes using safeguard markers:

struct {
  int low;
  int array[0xffff];
  int high;
} x;

low = -1;
high = -1;

do_some_job(&x);

assert((low == -1) && (high == -1));

This approach might be a valid strategy, but is it practical?
Uncertain. Foolproof? Definitely not: an out-of-bounds write could
easily occur 4 KiB past the array and be undetected.

While various testing methods exist, my original question wasn’t about
testing scenarios, but rather about potential methods to isolate and
protect compilation units from one another.

It appears this is not a novel idea and there are some solutions, for
example CHERI:
https://en.wikipedia.org/wiki/Capability_Hardware_Enhanced_RISC_Instructions

But this requires special hardware, while I am looking for something
that would be usable on Linux with commodity x86_64 hardware.

Mateusz

[toc] | [prev] | [next] | [standalone]


#393825

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-06-12 06:05 -0700
Message-ID<86wm9hp0u2.fsf@linuxsc.com>
In reply to#393805
Mateusz Viste <mateusz@x.invalid> writes:

> This might not be a strictly C question, but it definitely concerns all
> C programmers.
>
> Earlier today, I fixed an out-of-bounds write bug.  An obvious issue:
>
>   static int *socks[0xffff];
>
>   void update_my_socks(int *sock, int val) {
>     socks[val & 0xffff] = sock;
>   }
>
> While the presented issue is common knowledge for anyone familiar with
> C, *locating* the bug was challenging.  The program did not crash at the
> moment of the out-of-bounds write but much later - somewhere entirely
> different, in a different object file that maintained a static pointer
> for tracking a position in a linked list.  To my surprise, the pointer
> was randomly reset to NULL about once a week, causing a segfault.
> Tracing this back to an unrelated out-of-bounds write elsewhere in the
> code was tedious, to say the least.
>
> This raises a question:  how can such corruptions be detected sooner?
> Protected mode prevents interference between programs but doesn?t
> safeguard a program from corrupting itself.  Is there a way to enforce
> memory protection between module files of the same program?  After all,
> static objects shouldn't be accessible outside their compilation unit.
>
> How would you approach this?

The code in question shows several classic error patterns.  In no
particular order:

  * buffer overflow
  * off-by-one error
  * hard-coded constants (rather than symbolic)
  * bitwise operator with signed operand
  * using & to effect what is really a modulo operation
  * two of the above combine to impose a constraint on a
    hard-coded value, and the constraint is never checked

Of course some of these, notably buffer overflow, are hard to find.
But some of them are easy.  The hard-coded constants stand out like a
neon sign, especially because one is duplicated.  Check for any
constant written in open code above the value of, say, 10.  Once the
offending example is found, it can be rewritten, as for example

   static int *socks[0xffff];
   
   void update_my_socks(int *sock, int val) {
      const unsigned N = sizeof socks / sizeof socks[0];
      socks[val % N] = sock;
   }

This revision doesn't fix the program but it does eliminate the bug.
(Presumably fixing the program will happen later.)  Of course the
code should be further revised so that the temptation to use the
hard-coded value elsewhere is reduced, but this revision at least is
a step in the right direction.

Also, whenever a cockroach is seen, you can be sure there are other
cockroaches around.  Each of the types of errors evidenced by the
original code (at least three of the list of six types) represent
bugs waiting to be found;  go through the code and check for all
of them, at least for the ones that can be located easily.  Add
these error classes to the list of potential problems checked
during code review.

I acknowledge that this response isn't exactly an answer to the
original question.  It does illustrate though a kind of thinking
that can be useful when trying to track down hard-to-find bugs.

[toc] | [prev] | [next] | [standalone]


#393835

FromBonita Montero <Bonita.Montero@gmail.com>
Date2025-06-13 08:03 +0200
Message-ID<102geup$38k6o$2@raubtier-asyl.eternal-september.org>
In reply to#393825
Am 12.06.2025 um 15:05 schrieb Tim Rentsch:

>     void update_my_socks(int *sock, int val) {
>        const unsigned N = sizeof socks / sizeof socks[0];
>        socks[val % N] = sock;
>     }

For someone who uses bounds-checked containers in C++ every day
this really looks achaic.

[toc] | [prev] | [next] | [standalone]


#393849

Fromwij <wyniijj5@gmail.com>
Date2025-06-14 02:16 +0800
Message-ID<92d8fbd8b5ae741ee915fdf4d95e5a374108f37f.camel@gmail.com>
In reply to#393835
On Fri, 2025-06-13 at 08:03 +0200, Bonita Montero wrote:
> Am 12.06.2025 um 15:05 schrieb Tim Rentsch:
> 
> >     void update_my_socks(int *sock, int val) {
> >        const unsigned N = sizeof socks / sizeof socks[0];
> >        socks[val % N] = sock;
> >     }
> 
> For someone who uses bounds-checked containers in C++ every day
> this really looks achaic.

Really? What are they?

[toc] | [prev] | [next] | [standalone]


#393850

FromBonita Montero <Bonita.Montero@gmail.com>
Date2025-06-13 20:43 +0200
Message-ID<102hrgg$3jqq6$1@raubtier-asyl.eternal-september.org>
In reply to#393849
Am 13.06.2025 um 20:16 schrieb wij:
> On Fri, 2025-06-13 at 08:03 +0200, Bonita Montero wrote:
>> Am 12.06.2025 um 15:05 schrieb Tim Rentsch:
>>
>>>      void update_my_socks(int *sock, int val) {
>>>         const unsigned N = sizeof socks / sizeof socks[0];
>>>         socks[val % N] = sock;
>>>      }
>>
>> For someone who uses bounds-checked containers in C++ every day
>> this really looks achaic.
> 
> Really? What are they?

All containers with MSVC are bounds-checked wile debugging.
With libstdc++ (g++ / clang) you've to define a macro that
enables bounds-checking.

[toc] | [prev] | [next] | [standalone]


#393851

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-06-13 12:32 -0700
Message-ID<87v7ozh1yq.fsf@nosuchdomain.example.com>
In reply to#393849
wij <wyniijj5@gmail.com> writes:
> On Fri, 2025-06-13 at 08:03 +0200, Bonita Montero wrote:
>> Am 12.06.2025 um 15:05 schrieb Tim Rentsch:
>> 
>> >     void update_my_socks(int *sock, int val) {
>> >        const unsigned N = sizeof socks / sizeof socks[0];
>> >        socks[val % N] = sock;
>> >     }
>> 
>> For someone who uses bounds-checked containers in C++ every day
>> this really looks achaic.
>
> Really? What are they?

Feel free to discuss that in comp.lang.c++.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#393852

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-06-13 15:48 -0700
Message-ID<86sek3p8ai.fsf@linuxsc.com>
In reply to#393851
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> wij <wyniijj5@gmail.com> writes:
>
>> On Fri, 2025-06-13 at 08:03 +0200, Bonita Montero wrote:
>>
>>> Am 12.06.2025 um 15:05 schrieb Tim Rentsch:
>>>
>>>>  void update_my_socks(int *sock, int val) {
>>>>  const unsigned N = sizeof socks / sizeof socks[0];
>>>>  socks[val % N] = sock;
>>>>  }
>>>
>>> For someone who uses bounds-checked containers in C++ every day
>>> this really looks achaic.
>>
>> Really?  What are they?
>
> Feel free to discuss that in comp.lang.c++.

As a point of information, I have given up reading posts from
Bonita Montero.

[toc] | [prev] | [next] | [standalone]


#393838

FromMateusz Viste <mateusz@x.invalid>
Date2025-06-13 08:59 +0200
Message-ID<20250613085927.7b7cb344@mateusz>
In reply to#393825
On Thu, 12 Jun 2025 06:05 Tim Rentsch wrote:
> The code in question shows several classic error patterns.  In no
> particular order:
> 
>   * buffer overflow
>   * off-by-one error

I'd consider that one item, since one leads to another.

>   * bitwise operator with signed operand

My mistake. Real code is acting on something else than an int, I wasn't
paying enough attention when writing the illustrative example.

>   * using & to effect what is really a modulo operation

You think of it as modulo, I think of it as "bits trimming".
Essentially same operation, but different viewpoints I guess.

> I acknowledge that this response isn't exactly an answer to the
> original question.  It does illustrate though a kind of thinking
> that can be useful when trying to track down hard-to-find bugs.

Thank you for your insightful remarks. I completely agree - the best
way to debug a program is to avoid the need for debugging in the first
place. :-) But working with a large, 15-year-old codebase that has
seen contributions from dozens of programmers makes things a bit
non-ideal sometimes.

Mateusz

[toc] | [prev] | [next] | [standalone]


#393853

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-06-13 16:31 -0700
Message-ID<86o6urp6b5.fsf@linuxsc.com>
In reply to#393838
Mateusz Viste <mateusz@x.invalid> writes:

> On Thu, 12 Jun 2025 06:05 Tim Rentsch wrote:
>
>> The code in question shows several classic error patterns.  In no
>> particular order:
>>
>>   * buffer overflow
>>   * off-by-one error
>
> I'd consider that one item, since one leads to another.

You shouldn't.  Even if they seem to be related in this instance,
they are distinct kinds of errors.  The code I posted to eliminate
the buffer overflow does avoid that problem but it still had an
off-by-one error.

>>   * using & to effect what is really a modulo operation
>
> You think of it as modulo, I think of it as "bits trimming".
> Essentially same operation, but different viewpoints I guess.

It isn't wrong to think of bitwise-and as masking-in (or possibly
masking-out) of certain bits, but it still isn't a modulo.  A modulo
operation is what is desired;  in some cases that can be effected by
a bitwise-and, but in this case bitwise-and does the wrong thing.
The whole point is that it is NOT essentially the same operation.
It's a different operation, and in this case the wrong one.

>> I acknowledge that this response isn't exactly an answer to the
>> original question.  It does illustrate though a kind of thinking
>> that can be useful when trying to track down hard-to-find bugs.
>
> Thank you for your insightful remarks.  I completely agree - the best
> way to debug a program is to avoid the need for debugging in the first
> place. :-)  But working with a large, 15-year-old codebase that has
> seen contributions from dozens of programmers makes things a bit
> non-ideal sometimes.

I think you have misunderstood the point of my comments.  In some
cases one is confronted with a symptom that defies one's best
efforts to diagnose what is causing the symptom.  Looking for known
classes of errors is another arrow in the quiver of techniques for
discovering what is causing the observed behavior.  My point is that
there are several types of errors that could have been used, after
the fact, to uncover what was causing your problem here.  Taking
this approach might end up using a fair bit of time, but that time
is not wasted if it finds other potential lurking bugs, and there is
a good chance it will.

[toc] | [prev] | [next] | [standalone]


#393859

FromMateusz Viste <mateusz@not.gonna.tell>
Date2025-06-14 22:22 +0000
Message-ID<102ksmk$evka$1@dont-email.me>
In reply to#393853
On 14.06.2025 01:31, Tim Rentsch wrote:
>It isn't wrong to think of bitwise-and as masking-in (or possibly
>masking-out) of certain bits, but it still isn't a modulo.  A modulo
>operation is what is desired;

By "different viewpoints," I meant that while you approach the problem by
 applying a modulo operation to the index so it fits the array size, I tend
 to think in terms of ensuring the index correctly maps to a location within
 an n-bit address space. Naturally, the array should accommodate the maximum
 possible index for the given address space, and that’s where the original
 code fell short. And you're absolutely right that hardcoded values are
 problematic, the size of the array should have been linked with the n-bits
 address space expectation.

>I think you have misunderstood the point of my comments.  In some
>cases one is confronted with a symptom that defies one's best
>efforts to diagnose what is causing the symptom.  Looking for known
>classes of errors is another arrow in the quiver of techniques for
>discovering what is causing the observed behavior.

My remark was tongue-in-cheek, but we’re clearly on the same wavelengt, no
 worries. Digging into “known classes of errors” when facing bit-fiddling
 gremlins is precisely how I pinpointed the root cause, and proactively
 tracking other similar mistakes is on my todo. But this is an obvious,
 mechanical and uninteresting subject. As I mentioned to Michael earlier,
 improving code quality is a long-term, essential aspect of our work,
 there’s no question about that. But alongside this continuous effort, I’m
 always exploring strategies to be more defensive towards the current,
 non-ideal code.  

In this case, my initial thought was to split the program into smaller
 components that communicate via IPC. This approach would allow a faulty
 component to crash with a segfault without compromising the memory of other
 parts and greatly easing the debugging process. An IPC is much more
 limiting and slower than a function call, so it made me wonder if it is
 possible to achieve a similar level of isolation within a single program.
 That question led me to post here.  

While there is no magic solution yet, Kaz suggested a clever workaround
 using mprotect(), a compromise I’m considering applying in a few places.


Mateusz

[toc] | [prev] | [next] | [standalone]


#393957

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2025-07-01 09:54 -0700
Message-ID<86frffq2b7.fsf@linuxsc.com>
In reply to#393859
Mateusz Viste <mateusz@not.gonna.tell> writes:

> On 14.06.2025 01:31, Tim Rentsch wrote:
>
>> It isn't wrong to think of bitwise-and as masking-in (or possibly
>> masking-out) of certain bits, but it still isn't a modulo.  A
>> modulo operation is what is desired;
>
> By "different viewpoints," I meant that while you approach the
> problem by applying a modulo operation to the index so it fits the
> array size, I tend to think in terms of ensuring the index
> correctly maps to a location within an n-bit address space.
> Naturally, the array should accommodate the maximum possible index
> for the given address space, and that?s where the original code
> fell short.  And you're absolutely right that hardcoded values are
> problematic, the size of the array should have been linked with
> the n-bits address space expectation.

I understand what you're doing.  However one thinks of it, what is
needed is a way to ensure the produced index value is in the range
of array index values, and that the mapping covers the full range of
array index values.  Using bitwise-and is a way of solving a less
general problem.  Unfortunately:  one, although it is known that
using bitwise-and works only for certain array sizes, there was no
check or assertion in the code to verify that requirement;  two,
it's a holdover from earlier times when the performance difference
might matter, but now it's a premature optimization (and in most
cases does not result in any improvement);  and three, in this case
using bitwise-and contributed to the bug, which wouldn't have
happened if modulo had been used instead.

[toc] | [prev] | [next] | [standalone]


#393834

FromBonita Montero <Bonita.Montero@gmail.com>
Date2025-06-13 08:00 +0200
Message-ID<102geq8$38k6o$1@raubtier-asyl.eternal-september.org>
In reply to#393805
Am 11.06.2025 um 15:32 schrieb Mateusz Viste:

> While the presented issue is common knowledge for anyone familiar with
> C, *locating* the bug was challenging. The program did not crash at the
> moment of the out-of-bounds write but much later - somewhere entirely
> different, in a different object file that maintained a static pointer
> for tracking a position in a linked list. To my surprise, the pointer
> was randomly reset to NULL about once a week, causing a segfault.
> Tracing this back to an unrelated out-of-bounds write elsewhere in the
> code was tedious, to say the least.

Therefore I love bounds-checking C++ containers with MSVC (debug builds)
and with the libstdc++ runtime (enabled via macro). With that the bug
still remains in release-builds, but anyone who has access to the source
can run the code and apply suspicious input and can determine if there's
a bounds violation without knowing how the code works.
But sometimes you've got a simple memory range, usually from a C-API.
With that I use a C++20 span, that internally is usually a pointer and
a size_t. If you apply f.e. an indexed access on it the []-operator
checks the bounds with that.
Debug builds are usually much slower, but if you use C++ that's even
more slower since simple things like a container acces via []-operator
occur with a separate function call while debugging. With iterator
-debugging that's even slower. But this price is worth the advantage
that you can easily find bounds-problems with C++.


> This raises a question: how can such corruptions be detected sooner?

Use C++.

[toc] | [prev] | [next] | [standalone]


#393837

FromMateusz Viste <mateusz@x.invalid>
Date2025-06-13 08:47 +0200
Message-ID<20250613084717.2889aa4b@mateusz>
In reply to#393834
On Fri, 13 Jun 2025 08:00 Bonita Montero wrote:
> Therefore I love bounds-checking C++ containers with MSVC (debug
> builds) and with the libstdc++ runtime (enabled via macro). (...)
> Debug builds are usually much slower, but if you use C++ that's even
> more slower since simple things like a container acces via []-operator
> occur with a separate function call while debugging. With iterator
> -debugging that's even slower. But this price is worth the advantage
> that you can easily find bounds-problems with C++.

Sounds similar to Pixar's "Electric Fence" that Kaz mentioned earlier:
https://linux.die.net/man/3/efence

Depending on the performance impact this may or may not be a viable
solution to debug a rare production issue, but still nice to know it
exists.

Mateusz

[toc] | [prev] | [next] | [standalone]


#393845

FromKaz Kylheku <643-408-1753@kylheku.com>
Date2025-06-13 16:19 +0000
Message-ID<20250613091801.594@kylheku.com>
In reply to#393837
On 2025-06-13, Mateusz Viste <mateusz@x.invalid> wrote:
> On Fri, 13 Jun 2025 08:00 Bonita Montero wrote:
>> Therefore I love bounds-checking C++ containers with MSVC (debug
>> builds) and with the libstdc++ runtime (enabled via macro). (...)
>> Debug builds are usually much slower, but if you use C++ that's even
>> more slower since simple things like a container acces via []-operator
>> occur with a separate function call while debugging. With iterator
>> -debugging that's even slower. But this price is worth the advantage
>> that you can easily find bounds-problems with C++.
>
> Sounds similar to Pixar's "Electric Fence" that Kaz mentioned earlier:
> https://linux.die.net/man/3/efence
>
> Depending on the performance impact this may or may not be a viable
> solution to debug a rare production issue, but still nice to know it
> exists.

Saved my ass back in 1994. I cranked out an event-driven windowing
UI over ncurses and had a crash somewhere. The ncurses guys pointed
me to efence.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

[toc] | [prev] | [next] | [standalone]


#393867

FromLouis Krupp <lkrupp@invalid.pssw.com.invalid>
Date2025-06-16 06:29 -0600
Message-ID<K6U3Q.1005409$aGDe.643943@fx13.iad>
In reply to#393805
On 6/11/2025 7:32 AM, Mateusz Viste wrote:
> This might not be a strictly C question, but it definitely concerns all
> C programmers.
>
> Earlier today, I fixed an out-of-bounds write bug. An obvious issue:
>
>    static int *socks[0xffff];
>
>    void update_my_socks(int *sock, int val) {
>      socks[val & 0xffff] = sock;
>    }
>
> <snip>

Imagine an alternate universe in which array declarations took the form 
(borrowed from Unisys ALGOL):

array_name[lower_bound : upper_bound]

The array in question would have been declared

   static int *socks[0 : 0xffff]

The mask 0xffff and the upper bound would have been the same, and the 
code would have been obviously right instead of subtly wrong.

Louis

[toc] | [prev] | [next] | [standalone]


#393868

FromMateusz Viste <mateusz@x.invalid>
Date2025-06-16 15:01 +0200
Message-ID<20250616150128.2a980bac@mateusz>
In reply to#393867
On Mon, 16 Jun 2025 06:29:30 Louis Krupp wrote:
> Imagine an alternate universe in which array declarations took the
> form (borrowed from Unisys ALGOL):
> 
> array_name[lower_bound : upper_bound]

This alternate C universe you describe looks appealing, but I strongly
suspect it is currently tormented by violent conflicts between the
noble 0-based traditionalists, the idealistic 1-based reformists, and
the rogue "random-based" anarchists. Our C is not perfect, by we could
have ended with much worse.

Mateusz

[toc] | [prev] | [next] | [standalone]


#393905

Fromolcott <polcott333@gmail.com>
Date2025-06-21 15:49 -0500
Message-ID<10375s6$195fs$1@dont-email.me>
In reply to#393805
On 6/11/2025 8:32 AM, Mateusz Viste wrote:
> This might not be a strictly C question, but it definitely concerns all
> C programmers.
> 
> Earlier today, I fixed an out-of-bounds write bug. An obvious issue:
> 
>    static int *socks[0xffff];
> 
>    void update_my_socks(int *sock, int val) {
>      socks[val & 0xffff] = sock;
>    }
> 
> While the presented issue is common knowledge for anyone familiar with
> C, *locating* the bug was challenging. The program did not crash at the
> moment of the out-of-bounds write but much later - somewhere entirely
> different, in a different object file that maintained a static pointer
> for tracking a position in a linked list. To my surprise, the pointer
> was randomly reset to NULL about once a week, causing a segfault.
> Tracing this back to an unrelated out-of-bounds write elsewhere in the
> code was tedious, to say the least.
> 
> This raises a question: how can such corruptions be detected sooner?
> Protected mode prevents interference between programs but doesn’t
> safeguard a program from corrupting itself. Is there a way to enforce
> memory protection between module files of the same program? After all,
> static objects shouldn't be accessible outside their compilation unit.
> 
> How would you approach this?
> 
> Mateusz
> 

https://en.cppreference.com/w/c/types/integer.html
One way to fix the problem in the above specific
case is to define: void update_my_socks(int *sock, uint16_t val)


-- 
Copyright 2025 Olcott "Talent hits a target no one else can hit; Genius
hits a target no one else can see." Arthur Schopenhauer

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.c


csiph-web