Programming safe and secure code - generic
One should always write safe and secure code. Students should not get in the habit of writing insecure or buggy code. The following are minimum standards to follow.
Attribution and File Header
Each file should have comments at the top of the file giving a summary of what the file is. This should include the following elements.
- Author: your name
- Contents: what is this file for (e.g., hw 1 cs 500)
- Date: date handed in
- Summary: summary of a sentence or few - what does the program do or what is the file about, what changes did you make, etc.
- Attributions: list of sources you used. If you used AI you need to list the prompts you used, which AI was used, and if possible a link back to the AI's responses. If you discussed with anyone, list their names and the amount of discussion. If anyone looked at your code, you need to list that. If you copy/pasted code from anywhere, you need to indicate that and give a link to where you got it from. If you started with a file from class, you list that as well. If you have no attributions to list, then just put "none".
General Guidelines
- User input: user input should be validated to make sure it is within the range expected by the program. When user input is not valid, the program should either ask again or notify the user of the bad input and exit gracefully.
- Edge cases: the program should properly handle edge cases. For example, if computing an average of grades, the program should be correct if there are 0 grades (see above - that may be considered bad input), 1 grade, or more.
- Files: when opening a file for reading, the program should make sure it was opened successfully (i.e., that the file exists). When opening a file for writing, the program should make sure it was opened successfully (i.e., that it was a valid file name that the program has permission to write to). On failure, the program should notify the user and either ask again for a valid file name or exit gracefully.
- Function return values: for any (built in) functions that are used, the program should check their return value to make sure they completed successfully. If a function fails, the program should handle this appropriately (what to do depends on the individual case). For example, if using a function to open and read a website url, the program should check to make sure the link was read successfully before using the result.
C Programs
The following are specific to writing C programs.
- Inputting C strings: never use a method that reads arbitrarily long strings because this can result in a buffer overflow. For example: don't ever use
gets
, and if usingscanf
then do not do something likescanf("%d", &s);
but instead do something likechar s[100]; scanf("%99s", s);
. Note that this also applies to reading from files or other devices. - C string size: always allocate enough space for the largest string you will need + 1 for the terminating NULL character. For example, the following is not ok:
char s[5]; strcpy(s, "hello");
becauses
should have been declared with size at least 6. - Array size: any time your code accesses an array, make sure the index is valid (not negative and not past the end of the array). If the array index is ultimately coming from the user, then there needs to be a check somewhere to make sure it is in range.
- Large arrays: any array that takes up more than 10k bytes or so should be created using dynamic memory (i.e.,
malloc
). Do not do something like this:char buffer[10000000];
because variables that are declared like this are in the "memory stack" which does not have enough space to hold large arrays (this can result in a "stack overflow"). - Malloc'ed memory: any memory that is from the "memory heap" (e.g., coming from using
malloc
,realloc
, or other functions likegetline
that returns memory from the memory heap) needs to be free'ed before the program ends. Not free'ing malloc'ed memory is a memory leak which can result in poor performance or your program crashing. - Dereferencing pointers: always make sure that a pointer you are dereferencing is valid (.e.g, not NULL). Note that pointers are typically dereferenced with
*
,->
, or[ ]
, or by passing the pointer to a built in function.