Answers.Body: <h3>Exercises for array bounds</h3>
  <p>String manipulation code very often runs into array bounds.</p>
  <p>For simple exercises, arrange two-part problems where the first part allocates memory for a string and the second part modifies that string in place. This forces students to distinguish between the data size and the allocated size. For example: read a line from a file by growing a buffer until you find a newline; then perform some transformation that might expand the line (e.g. a substring replacement or a format conversion).</p>
  <p>For some more complex exercises, do some parsing of binary protocols with length-value encodings. This is a very common source of buffer overflows in real-world code. For example, <a href="https://www.kb.cert.org/vuls/id/512705" rel="nofollow noreferrer">one that allowed exploiting computers provided that they were powered off</a>! (A bug in a Wake-on-LAN implementation in network card firmware.) This forces students to distinguish between the purported size (encoded in the string) and the actual size (bounded by the size of the complete input).</p>
  <h3>Exercises for memory management</h3>
  <p>In high-quality C code bases, buffer overflows tend to be rare, because it's not that hard to be disciplined about them. Memory management bugs are harder. Manual memory management is hard, and often the reason you need it is that you can't be very disciplined about it. So you should train your students to watch out for use-after-free and double-free, as well as memory leaks.</p>
  <p>A very common case for a memory management bug is a program that needs to allocate two resources (such as two malloc'ed objects), and where a recoverable error can happen either after obtaining the first resource or after obtaining the second resource.</p>
  <ul>
  <li>If the cleanup code tries to access the a resource whose allocation failed, you may have an access to uninitialized memory (possibly leading to dereferencing an arbitrary pointer object). In more disciplined code, where all pointers are initialized to <code>NULL</code>, you have a null pointer dereference.</li>
  <li>If the cleanup code tries to access one of the resources after it has deallocated it, you may have a use-after-free.</li>
  <li>If the cleanup code ends up freeing a resource twice (e.g. due to partial cleanup on a specific error path followed by a generic cleanup), you may have a double free.</li>
  <li>If some cleanup code is missing, you may have a memory leak.</li>
  </ul>
  <p>Here are a few examples of long-lived programs that allocate multiple resources for a single task:</p>
  <ul>
  <li>A server allocates a send buffer and a receive buffer.</li>
  <li>A data processing server, or a data processing interactive tool, that allocates multiple buffers to process each request.</li>
  </ul>
  <p>Memory management errors also arise in code that manipulates complex data structures (trees, linked lists, hash tables, graphs, …). But that tends to make for more advanced exercises because the parts about the data structure itself are usually complex.</p>
  <h3>Tooling</h3>
  <p>Please teach your students tooling that can help them. As a practitioner, I find <a href="https://github.com/google/sanitizers/wiki/AddressSanitizer" rel="nofollow noreferrer">ASan (Address Sanitizer)</a> very useful. It will find most out-of-bounds accesses, use-after-free/double-free and memory leaks as long as there is a test case that reaches them.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-12-24T22:24:33.503Z
Answers.Text: Perhaps OP should use ASan or similar tools to check the memory-safety of their students' code?  (Memory errors, like concurrency errors, are notoriously difficult to trigger when testing — they tend to show themselves only ‘in the wild’ where they can do much more damage!)
Answers.UserDisplayName: gidds
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-12-26T19:49:26.227Z
Answers.Text: @gidds Yes, but OP should also teach their students to do it.
Answers.UserDisplayName: Gilles 'SO- stop being evil'
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-12-11T21:50:10.090Z
Answers.LastActivityDate: 2023-12-11T21:50:10.090Z
Answers.UserDisplayName: Gilles 'SO- stop being evil'
Body: <p>I am looking for a coding exercise that could be assigned to students and will give them practice with writing <a href="https://en.wikipedia.org/wiki/Memory_safety" rel="nofollow noreferrer">memory-safe</a> code.  In particular, I am looking for some exercise that students would have to implement in C, and where if they aren't cautious, it would be easy to introduce a memory-safety vulnerability -- e.g., an array out-of-bounds bug, or a <a href="https://en.wikipedia.org/wiki/Buffer_overflow" rel="nofollow noreferrer">buffer overrun vulnerability</a>.  Can anyone suggest a programming exercise that might be suitable?</p>
  <p>I am hoping that having the experience of writing code that turns out to contain such a vulnerability might motivate interest in tools and techniques to assist with ensuring code is memory-safe.</p>
  <p>To give an analogy: one classic exercise is to implement binary search in a sorted array.  If you're not careful, it's easy to introduce an off-by-one bug into your code, so this is a good exercise to motivate loop invariants as a technique for writing correct code.  Is there a coding exercise like this, aimed not at off-by-one bugs and loop variants, but at memory safety or buffer overruns or array bounds errors?</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-11-27T20:26:31.047Z
Comments.Text: Just about any C program that requires heap memory seems like it'd fit the bill. I can't think of too many nontrivial C programs I've written that didn't involve running into memory safety problems at some point. Beyond that, does the project need to be greenfield? You could have them analyze and fix bugs in a small codebase with existing memory safety problems.
Comments.UserDisplayName: ggorlen
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-11-28T04:51:53.363Z
Comments.Text: @ggorlen, Thanks for your comment, but that's not what I'm looking for, and does not match my experience.  The chances of having a memory safety error are significantly higher for some coding tasks, and lower for others.  I want a coding exercise where the chances are as high as possible.  (For many small-sized coding tasks that are not chosen with this purpose in mind, if they program in a vaguely reasonable way, there is a significant chance they will have no memory safety problems.)Yes, I really do want a project where they write their own code, not analyze/fix bugs in an existing codebase.
Comments.UserDisplayName: D.W.
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-11-28T04:54:47.387Z
Comments.Text: Sounds like you're a much better C programmer than I am, then.
Comments.UserDisplayName: ggorlen
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2023-11-28T05:11:29.920Z
Comments.Text: @ggorlen, Well, no, that's not my basis for asking.  I ask for faith that I have good reason for asking.  I have experience with one attempt at such an exercise; the prevalence of memory safety errors in student solutions was not what I was hoping for.  So I'm asking here hoping that others have a better solution.
Comments.UserDisplayName: D.W.
Tags: <programming><exercises><security>
Title: Coding exercises that test memory safety
ThreadText: # Coding exercises that test memory safety
  
  (Asked by: username_0 on 2023-11-27)
  
  I am looking for a coding exercise that could be assigned to students and will give them practice with writing [memory-safe](https://en.wikipedia.org/wiki/Memory_safety) code. In particular, I am looking for some exercise that students would have to implement in C, and where if they aren't cautious, it would be easy to introduce a memory-safety vulnerability -- e.g., an array out-of-bounds bug, or a [buffer overrun vulnerability](https://en.wikipedia.org/wiki/Buffer_overflow). Can anyone suggest a programming exercise that might be suitable?
  
  I am hoping that having the experience of writing code that turns out to contain such a vulnerability might motivate interest in tools and techniques to assist with ensuring code is memory-safe.
  
  To give an analogy: one classic exercise is to implement binary search in a sorted array. If you're not careful, it's easy to introduce an off-by-one bug into your code, so this is a good exercise to motivate loop invariants as a technique for writing correct code. Is there a coding exercise like this, aimed not at off-by-one bugs and loop variants, but at memory safety or buffer overruns or array bounds errors?
  
  **Tags:** programming, exercises, security
  
  > **Comments:**
  > **username_1**: Just about any C program that requires heap memory seems like it'd fit the bill. I can't think of too many nontrivial C programs I've written that didn't involve running into memory safety problems at some point. Beyond that, does the project need to be greenfield? You could have them analyze and fix bugs in a small codebase with existing memory safety problems.  
  > **username_0**: @username_1, Thanks for your comment, but that's not what I'm looking for, and does not match my experience.  The chances of having a memory safety error are significantly higher for some coding tasks, and lower for others.  I want a coding exercise where the chances are as high as possible.  (For many small-sized coding tasks that are not chosen with this purpose in mind, if they program in a vaguely reasonable way, there is a significant chance they will have no memory safety problems.)Yes, I really do want a project where they write their own code, not analyze/fix bugs in an existing codebase.  
  > **username_1**: Sounds like you're a much better C programmer than I am, then.  
  > **username_0**: @username_1, Well, no, that's not my basis for asking.  I ask for faith that I have good reason for asking.  I have experience with one attempt at such an exercise; the prevalence of memory safety errors in student solutions was not what I was hoping for.  So I'm asking here hoping that others have a better solution.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2023-12-11. Score: 3
  
  ### Exercises for array bounds
  
  String manipulation code very often runs into array bounds.
  
  For simple exercises, arrange two-part problems where the first part allocates memory for a string and the second part modifies that string in place. This forces students to distinguish between the data size and the allocated size. For example: read a line from a file by growing a buffer until you find a newline; then perform some transformation that might expand the line (e.g. a substring replacement or a format conversion).
  
  For some more complex exercises, do some parsing of binary protocols with length-value encodings. This is a very common source of buffer overflows in real-world code. For example, [one that allowed exploiting computers provided that they were powered off](https://www.kb.cert.org/vuls/id/512705)! (A bug in a Wake-on-LAN implementation in network card firmware.) This forces students to distinguish between the purported size (encoded in the string) and the actual size (bounded by the size of the complete input).
  
  ### Exercises for memory management
  
  In high-quality C code bases, buffer overflows tend to be rare, because it's not that hard to be disciplined about them. Memory management bugs are harder. Manual memory management is hard, and often the reason you need it is that you can't be very disciplined about it. So you should train your students to watch out for use-after-free and double-free, as well as memory leaks.
  
  A very common case for a memory management bug is a program that needs to allocate two resources (such as two malloc'ed objects), and where a recoverable error can happen either after obtaining the first resource or after obtaining the second resource.
  
  * If the cleanup code tries to access the a resource whose allocation failed, you may have an access to uninitialized memory (possibly leading to dereferencing an arbitrary pointer object). In more disciplined code, where all pointers are initialized to `NULL`, you have a null pointer dereference.
  * If the cleanup code tries to access one of the resources after it has deallocated it, you may have a use-after-free.
  * If the cleanup code ends up freeing a resource twice (e.g. due to partial cleanup on a specific error path followed by a generic cleanup), you may have a double free.
  * If some cleanup code is missing, you may have a memory leak.
  
  Here are a few examples of long-lived programs that allocate multiple resources for a single task:
  
  * A server allocates a send buffer and a receive buffer.
  * A data processing server, or a data processing interactive tool, that allocates multiple buffers to process each request.
  
  Memory management errors also arise in code that manipulates complex data structures (trees, linked lists, hash tables, graphs, …). But that tends to make for more advanced exercises because the parts about the data structure itself are usually complex.
  
  ### Tooling
  
  Please teach your students tooling that can help them. As a practitioner, I find [ASan (Address Sanitizer)](https://github.com/google/sanitizers/wiki/AddressSanitizer) very useful. It will find most out-of-bounds accesses, use-after-free/double-free and memory leaks as long as there is a test case that reaches them.
  
  > **Comments:**
  > **username_3**: Perhaps OP should use ASan or similar tools to check the memory-safety of their students' code?  (Memory errors, like concurrency errors, are notoriously difficult to trigger when testing — they tend to show themselves only ‘in the wild’ where they can do much more damage!)  
  > **username_2**: @username_3 Yes, but OP should also teach their students to do it.  
  
  ---
  
  