Skip to content

Commit

Permalink
Merge branch 'sysprog21:master' into master
Browse files Browse the repository at this point in the history
m561247 authored Apr 26, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents c75b4d8 + bef955a commit 3db3bd0
Showing 11 changed files with 133 additions and 42 deletions.
22 changes: 22 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -11,6 +11,24 @@ Use your best judgment, and feel free to propose changes to this document in a p
This project uses GitHub Issues to track ongoing development, discuss project plans, and keep track of bugs.
Be sure to search for existing issues before you create another one.

Initially, it is advisable to create an issue on GitHub for bug reports, feature requests,
or substantial pull requests, as this offers a platform for discussion with both the community and project maintainers.

Engaging in a conversation through a GitHub issue before making a contribution is crucial to ensure the acceptance of your work.
We aim to prevent situations where significant effort is expended on a pull request that might not align with the project's design principles.
For example, it might turn out that the feature you propose is more suited as an independent module that complements this project,
in which case we would recommend that direction.

For minor corrections, such as typo fixes, small refactoring, or updates to documentation/comments,
filing an issue is not typically necessary.
What constitutes a "minor" fix involves discretion; however, examples include:
- Correcting spelling mistakes
- Minor code refactoring
- Updating or editing documentation and comments

Nevertheless, there may be instances where, upon reviewing your pull requests,
we might request an issue to be filed to facilitate discussion on broader design considerations.

Visit our [Issues page on GitHub](https://github.com/sysprog21/lab0-c/issues) to search and submit.

## Coding Convention
@@ -21,6 +39,10 @@ However, participation requires adherence to fundamental ground rules:
While there is some flexibility in basic style, it is crucial to stick to the current coding standards.
Complex algorithmic constructs without proper comments will not be accepted.
* External pull requests should include thorough documentation in the pull request comments for consideration.
* When composing documentation, code comments, and other materials in English,
please adhere to the American English (`en_US`) dialect.
This variant should be considered the standard for all documentation efforts.
For instance, opt for "initialize" over "initialise" and "color" rather than "colour".

Software requirement: [clang-format](https://clang.llvm.org/docs/ClangFormat.html) version 12 or later.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -29,9 +29,9 @@ Some distros like Arch Linux won't install `aspell-en` with `aspell`, and you mu
$ sudo pacman -S aspell-en
```

Note: [Cppcheck](http://cppcheck.sourceforge.net/) version must be at least 1.90, otherwise
Note: [Cppcheck](https://cppcheck.sourceforge.net/) version must be at least 1.90, otherwise
it might report errors with false positives. You can get its version by executing `$ cppcheck --version`.
Check [Developer Info](http://cppcheck.sourceforge.net/devinfo/) for building Cppcheck from source.
Check [Developer Info](https://cppcheck.sourceforge.net/devinfo/) for building Cppcheck from source.

### Integrate `clang-format` to `vim`
If you want to run `clang-format` automatically after saving with vim,
39 changes: 29 additions & 10 deletions harness.c
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

#include <setjmp.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -58,6 +59,12 @@ static jmp_buf env;
static volatile sig_atomic_t jmp_ready = false;
static bool time_limited = false;

/* For test_malloc and test_calloc */
typedef enum {
TEST_MALLOC,
TEST_CALLOC,
} alloc_t;

/* Internal functions */

/* Should this allocation fail? */
@@ -115,17 +122,23 @@ static size_t *find_footer(block_element_t *b)
return p;
}

/* Implementation of application functions */

void *test_malloc(size_t size)
static void *alloc(alloc_t alloc_type, size_t size)
{
if (noallocate_mode) {
report_event(MSG_FATAL, "Calls to malloc disallowed");
char *msg_alloc_forbidden[] = {
"Calls to malloc are disallowed",
"Calls to calloc are disallowed",
};
report_event(MSG_FATAL, "%s", msg_alloc_forbidden[alloc_type]);
return NULL;
}

if (fail_allocation()) {
report_event(MSG_WARN, "Malloc returning NULL");
char *msg_alloc_failure[] = {
"Malloc returning NULL",
"Calloc returning NULL",
};
report_event(MSG_WARN, "%s", msg_alloc_failure[alloc_type]);
return NULL;
}

@@ -142,7 +155,7 @@ void *test_malloc(size_t size)
new_block->payload_size = size;
*find_footer(new_block) = MAGICFOOTER;
void *p = (void *) &new_block->payload;
memset(p, FILLCHAR, size);
memset(p, !alloc_type * FILLCHAR, size);
// cppcheck-suppress nullPointerRedundantCheck
new_block->next = allocated;
// cppcheck-suppress nullPointerRedundantCheck
@@ -156,16 +169,22 @@ void *test_malloc(size_t size)
return p;
}

/* Implementation of application functions */

void *test_malloc(size_t size)
{
return alloc(TEST_MALLOC, size);
}

// cppcheck-suppress unusedFunction
void *test_calloc(size_t nelem, size_t elsize)
{
/* Reference: Malloc tutorial
* https://danluu.com/malloc-tutorial/
*/
size_t size = nelem * elsize; // TODO: check for overflow
void *ptr = test_malloc(size);
memset(ptr, 0, size);
return ptr;
if (!nelem || !elsize || nelem > SIZE_MAX / elsize)
return NULL;
return alloc(TEST_CALLOC, nelem * elsize);
}

void test_free(void *p)
1 change: 1 addition & 0 deletions harness.h
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ void trigger_exception(char *msg);

/* Tested program use our versions of malloc and free */
#define malloc test_malloc
#define calloc test_calloc
#define free test_free

/* Use undef to avoid strdup redefined error */
62 changes: 53 additions & 9 deletions qtest.c
Original file line number Diff line number Diff line change
@@ -172,9 +172,11 @@ static void fill_rand_string(char *buf, size_t buf_size)
while (len < MIN_RANDSTR_LEN)
len = rand() % buf_size;

randombytes((uint8_t *) buf, len);
uint64_t randstr_buf_64[MAX_RANDSTR_LEN] = {0};
randombytes((uint8_t *) randstr_buf_64, len * sizeof(uint64_t));
for (size_t n = 0; n < len; n++)
buf[n] = charset[buf[n] % (sizeof(charset) - 1)];
buf[n] = charset[randstr_buf_64[n] % (sizeof(charset) - 1)];

buf[len] = '\0';
}

@@ -540,11 +542,6 @@ static bool do_size(int argc, char *argv[])

int reps = 1;
bool ok = true;
if (argc != 1 && argc != 2) {
report(1, "%s needs 0-1 arguments", argv[0]);
return false;
}

if (argc == 2) {
if (!get_int(argv[1], &reps))
report(1, "Invalid number of calls to size '%s'", argv[2]);
@@ -598,6 +595,23 @@ bool do_sort(int argc, char *argv[])
error_check();

set_noallocate_mode(true);

/* If the number of elements is too large, it may take a long time to check the
* stability of the sort. So, MAX_NODES is used to limit the number of elements
* to check the stability of the sort. */
#define MAX_NODES 100000
struct list_head *nodes[MAX_NODES];
unsigned no = 0;
if (current && current->size && current->size <= MAX_NODES) {
element_t *entry;
list_for_each_entry (entry, current->q, list)
nodes[no++] = &entry->list;
} else if (current && current->size > MAX_NODES)
report(1,
"Warning: Skip checking the stability of the sort because the "
"number of elements %d is too large, exceeds the limit %d.",
current->size, MAX_NODES);

if (current && exception_setup(true))
q_sort(current->q, descend);
exception_cancel();
@@ -622,8 +636,32 @@ bool do_sort(int argc, char *argv[])
ok = false;
break;
}
/* Ensure the stability of the sort */
if (current->size <= MAX_NODES &&
!strcmp(item->value, next_item->value)) {
bool unstable = false;
for (unsigned i = 0; i < MAX_NODES; i++) {
if (nodes[i] == cur_l->next) {
unstable = true;
break;
}
if (nodes[i] == cur_l) {
break;
}
}
if (unstable) {
report(
1,
"ERROR: Not stable sort. The duplicate strings \"%s\" "
"are not in the same order.",
item->value);
ok = false;
break;
}
}
}
}
#undef MAX_NODES

q_show(3);
return ok && !error_check();
@@ -878,17 +916,23 @@ static bool do_merge(int argc, char *argv[])
static bool is_circular()
{
struct list_head *cur = current->q->next;
struct list_head *fast = (cur) ? cur->next : NULL;
while (cur != current->q) {
if (!cur)
if (!cur || !fast || !fast->next)
return false;
if (cur == fast)
return false;
cur = cur->next;
fast = fast->next->next;
}

cur = current->q->prev;
fast = (cur) ? cur->prev : NULL;
while (cur != current->q) {
if (!cur)
if (!cur || !fast || !fast->prev)
return false;
cur = cur->prev;
fast = fast->prev->prev;
}
return true;
}
4 changes: 3 additions & 1 deletion queue.h
Original file line number Diff line number Diff line change
@@ -151,7 +151,7 @@ bool q_delete_mid(struct list_head *head);
* Reference:
* https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
*
* Return: true for success, false if list is NULL.
* Return: true for success, false if list is NULL or empty.
*/
bool q_delete_dup(struct list_head *head);

@@ -207,6 +207,7 @@ void q_sort(struct list_head *head, bool descend);
*
* No effect if queue is NULL or empty. If there has only one element, do
* nothing.
* Memory allocated to removed nodes must be freed.
*
* Reference:
* https://leetcode.com/problems/remove-nodes-from-linked-list/
@@ -222,6 +223,7 @@ int q_ascend(struct list_head *head);
*
* No effect if queue is NULL or empty. If there has only one element, do
* nothing.
* Memory allocated to removed nodes must be freed.
*
* Reference:
* https://leetcode.com/problems/remove-nodes-from-linked-list/
30 changes: 14 additions & 16 deletions random.c
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ static ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
}
#endif

static int randombytes_linux_randombytes_getrandom(void *buf, size_t n)
static int linux_getrandom(void *buf, size_t n)
{
size_t offset = 0;
int ret;
@@ -114,12 +114,12 @@ static int randombytes_linux_randombytes_getrandom(void *buf, size_t n)
#if defined(__linux__) && !defined(SYS_getrandom)

#if defined(__linux__)
static inline int randombytes_linux_read_entropy_ioctl(int device, int *entropy)
static inline int linux_read_entropy_ioctl(int device, int *entropy)
{
return ioctl(device, RNDGETENTCNT, entropy);
}

static int randombytes_linux_read_entropy_proc(FILE *stream, int *entropy)
static int linux_read_entropy_proc(FILE *stream, int *entropy)
{
int retcode;
do {
@@ -131,7 +131,7 @@ static int randombytes_linux_read_entropy_proc(FILE *stream, int *entropy)
return 0;
}

static int randombytes_linux_wait_for_entropy(int device)
static int linux_wait_for_entropy(int device)
{
/* We will block on /dev/random, because any increase in the OS' entropy
* level will unblock the request. I use poll here (as does libsodium),
@@ -144,7 +144,7 @@ static int randombytes_linux_wait_for_entropy(int device)
int entropy = 0;

/* If the device has enough entropy already, we will want to return early */
int retcode = randombytes_linux_read_entropy_ioctl(device, &entropy);
int retcode = linux_read_entropy_ioctl(device, &entropy);
if (retcode != 0 && (errno == ENOTTY || errno == ENOSYS)) {
/* The ioctl call on /dev/urandom has failed due to a
* - ENOTTY (unsupported action), or
@@ -184,11 +184,9 @@ static int randombytes_linux_wait_for_entropy(int device)
continue;
} else if (retcode == 1) {
if (strategy == IOCTL) {
retcode =
randombytes_linux_read_entropy_ioctl(device, &entropy);
retcode = linux_read_entropy_ioctl(device, &entropy);
} else if (strategy == PROC) {
retcode =
randombytes_linux_read_entropy_proc(proc_file, &entropy);
retcode = linux_read_entropy_proc(proc_file, &entropy);
} else {
return -1; /* Unreachable */
}
@@ -220,7 +218,7 @@ static int randombytes_linux_wait_for_entropy(int device)
}
#endif /* defined(__linux__) */

static int randombytes_linux_randombytes_urandom(void *buf, size_t n)
static int linux_urandom(void *buf, size_t n)
{
int fd;
do {
@@ -229,7 +227,7 @@ static int randombytes_linux_randombytes_urandom(void *buf, size_t n)
if (fd == -1)
return -1;
#if defined(__linux__)
if (randombytes_linux_wait_for_entropy(fd) == -1)
if (linux_wait_for_entropy(fd) == -1)
return -1;
#endif

@@ -259,7 +257,7 @@ static int randombytes_linux_randombytes_urandom(void *buf, size_t n)
#include <CommonCrypto/CommonRandom.h>
#endif
#endif
static int randombytes_bsd_randombytes(void *buf, size_t n)
static int bsd_randombytes(void *buf, size_t n)
{
#if defined(MAC_OS_X_VERSION_10_15) && \
MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15
@@ -279,16 +277,16 @@ int randombytes(uint8_t *buf, size_t n)
#if defined(__linux__) || defined(__GNU__)
#if defined(USE_GLIBC)
/* Use getrandom system call */
return randombytes_linux_randombytes_getrandom(buf, n);
return linux_getrandom(buf, n);
#elif defined(SYS_getrandom)
/* Use getrandom system call */
return randombytes_linux_randombytes_getrandom(buf, n);
return linux_getrandom(buf, n);
#else
/* When we have enough entropy, we can read from /dev/urandom */
return randombytes_linux_randombytes_urandom(buf, n);
return linux_urandom(buf, n);
#endif
#elif defined(BSD)
return randombytes_bsd_randombytes(buf, n);
return bsd_randombytes(buf, n);
#else
#error "randombytes(...) is not supported on this platform"
#endif
2 changes: 1 addition & 1 deletion report.c
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ void report_event(message_t msg, char *fmt, ...)
"ERROR",
"FATAL ERROR",
};
char *msg_name = msg_name_text[2];
const char *msg_name = msg_name_text[2];
if (msg < N_MSG)
msg_name = msg_name_text[msg];
int level = N_MSG - msg - 1;
3 changes: 3 additions & 0 deletions scripts/aspell-pws
Original file line number Diff line number Diff line change
@@ -292,3 +292,6 @@ adjtime
perf
uring
Shannon
http
https
tcp
2 changes: 1 addition & 1 deletion scripts/checksums
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
444bab14cb8ad4c949f61b3c10a22a3ed2401425 queue.h
db6784ff3917888db4d1dceaa0570d99ed40e762 queue.h
3337dbccc33eceedda78e36cc118d5a374838ec7 list.h
6 changes: 4 additions & 2 deletions scripts/pre-commit.hook
Original file line number Diff line number Diff line change
@@ -19,7 +19,9 @@ CPPCHECK_suppresses="--inline-suppr harness.c \
--suppress=returnDanglingLifetime:report.c \
--suppress=constParameterCallback:console.c \
--suppress=constParameterPointer:console.c \
--suppress=checkLevelNormal:log2_lshift16.h"
--suppress=checkLevelNormal:log2_lshift16.h \
--suppress=preprocessorErrorDirective:random.h \
"
CPPCHECK_OPTS="-I. --enable=all --error-exitcode=1 --force $CPPCHECK_suppresses $CPPCHECK_unmatched ."

RETURN=0
@@ -43,7 +45,7 @@ if [ -z "$($CPPCHECK --version | grep -E '^Cppcheck\s2')" ]; then
if [ $CPPCHECK_VER -lt 90 ]; then
echo "[!] cppcheck version must be at least 1.90." >&2
echo -e " Check 'Developer Info' for building Cppcheck from source:\n" \
" http://cppcheck.sourceforge.net/devinfo/" >&2
" https://cppcheck.sourceforge.net/devinfo/" >&2
exit 1
fi
fi

0 comments on commit 3db3bd0

Please sign in to comment.