Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #393805 > unrolled thread
| Started by | Mateusz Viste <mateusz@x.invalid> |
|---|---|
| First post | 2025-06-11 15:32 +0200 |
| Last post | 2025-06-21 15:49 -0500 |
| Articles | 18 on this page of 58 — 21 participants |
Back to article view | Back to comp.lang.c
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]
| From | Mikko <mikko.levanto@iki.fi> |
|---|---|
| Date | 2025-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]
| From | Mateusz Viste <mateusz@x.invalid> |
|---|---|
| Date | 2025-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2025-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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-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]
| From | wij <wyniijj5@gmail.com> |
|---|---|
| Date | 2025-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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2025-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2025-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]
| From | Mateusz Viste <mateusz@x.invalid> |
|---|---|
| Date | 2025-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2025-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]
| From | Mateusz Viste <mateusz@not.gonna.tell> |
|---|---|
| Date | 2025-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]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2025-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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2025-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]
| From | Mateusz Viste <mateusz@x.invalid> |
|---|---|
| Date | 2025-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]
| From | Kaz Kylheku <643-408-1753@kylheku.com> |
|---|---|
| Date | 2025-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]
| From | Louis Krupp <lkrupp@invalid.pssw.com.invalid> |
|---|---|
| Date | 2025-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]
| From | Mateusz Viste <mateusz@x.invalid> |
|---|---|
| Date | 2025-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]
| From | olcott <polcott333@gmail.com> |
|---|---|
| Date | 2025-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