From 2bdb57390d9ea3a04f3fc2c709ed3eb4bde10401 Mon Sep 17 00:00:00 2001 From: javalsai Date: Wed, 11 Jun 2025 14:40:21 +0200 Subject: [PATCH] lint: satisfy some nullability annotations --- .clang-tidy | 2 ++ include/desktop.h | 7 +++--- include/macros.h | 6 +++++ src/desktop.c | 22 +++++------------ src/sessions.c | 60 +++++++++++++++++++++++++---------------------- 5 files changed, 50 insertions(+), 47 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index f653445..a81f57c 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,7 @@ Checks: > clang-analyzer-*, + -clang-analyzer-security.insecureAPI.str*, + -clang-analyzer-security.insecureAPI.mem*, bugprone-*, cert-*, modernize-*, diff --git a/include/desktop.h b/include/desktop.h index a83e55c..3842d20 100644 --- a/include/desktop.h +++ b/include/desktop.h @@ -11,8 +11,9 @@ struct status { int ret; }; -int read_desktop(FILE* fd, void* ctx, - struct status (*cb)(void* ctx, char* NULLABLE table, char* key, - char* value)); +int read_desktop(FILE* NNULLABLE fd, void* UNULLABLE ctx, + struct status (*NNULLABLE cb)(void* UNULLABLE ctx, char* NULLABLE table, + char* NNULLABLE key, + char* NNULLABLE value)); #endif diff --git a/include/macros.h b/include/macros.h index 2b1fd0e..d8f6882 100644 --- a/include/macros.h +++ b/include/macros.h @@ -10,3 +10,9 @@ #else #define NNULLABLE #endif + +#if defined(__clang__) +#define UNULLABLE _Null_unspecified +#else +#define UNULLABLE +#endif diff --git a/src/desktop.c b/src/desktop.c index 90ab141..b3ed57f 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -7,18 +7,8 @@ #include "desktop.h" #include "macros.h" -#define NOK \ - { \ - ret = -1; \ - break; \ - } -#define NOKFKEY \ - { \ - free(key); \ - NOK \ - } int read_desktop(FILE* fd, void* ctx, - struct status (*cb)(void* ctx, char* NULLABLE table, char* key, + struct status (*cb)(void* ctx, char* table, char* key, char* value)) { char* table_name = NULL; @@ -47,7 +37,10 @@ int read_desktop(FILE* fd, void* ctx, // impossible with a min len of 1 (empty line) if (eq_idx == 0) continue; // Check its not end - if (buf[eq_idx] != '=') NOK; + if (buf[eq_idx] != '=') { + ret = -1; + break; + } // Key & Value char* key = buf; @@ -64,11 +57,8 @@ int read_desktop(FILE* fd, void* ctx, } } - free(table_name); - + if (table_name != NULL) free(table_name); if (buf != NULL) free(buf); return ret; } -#undef NOK -#undef NOKFKEY // NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity) diff --git a/src/sessions.c b/src/sessions.c index e96b5e9..4f0b010 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -20,22 +20,16 @@ static const struct source_dir sources[] = { {WAYLAND, "/usr/share/wayland-sessions"}, }; -// static struct session new_session(enum session_type type, char* name, -// const char* exec, const char* tryexec) { -// struct session session; -// session.type = type; -// strcln(&session.name, name); -// strcln(&session.exec, exec); -// strcln(&session.tryexec, tryexec); - -// return session; -// } - static struct Vector* cb_sessions = NULL; +struct ctx_typ { + char* NULLABLE name; + char* NULLABLE exec; + char* NULLABLE tryexec; +}; // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) struct status cb(void* _ctx, char* NULLABLE table, char* key, char* value) { - struct session* ctx = (struct session*)_ctx; + struct ctx_typ* ctx = (struct ctx_typ*)_ctx; struct status ret; ret.finish = false; @@ -52,13 +46,11 @@ struct status cb(void* _ctx, char* NULLABLE table, char* key, char* value) { } if (copy_at != NULL) { - *copy_at = malloc((strlen(value) + 1) * sizeof(char)); + *copy_at = strdup(value); if (*copy_at == NULL) { ret.finish = true; ret.ret = -1; // malloc error } - - strcpy(*copy_at, value); } if (ctx->name != NULL && ctx->exec != NULL && ctx->tryexec != NULL) { @@ -69,38 +61,50 @@ struct status cb(void* _ctx, char* NULLABLE table, char* key, char* value) { return ret; } +// also, always return 0 or we will break parsing and we don't want a bad +// desktop file to break all possible sessions static enum session_type session_type; // NOLINTNEXTLINE(readability-function-cognitive-complexity) static int fn(const char* fpath, const struct stat* sb, int typeflag) { - if (!S_ISREG(sb->st_mode)) return 0; + // guessing symlink behavior + // - FTW_PHYS if set doesn't follow symlinks, so ftw() has no flags and it + // follows symlinks, we should never get to handle that + if (typeflag != FTW_F) return 0; - struct session* ctx = malloc(sizeof(struct session)); - if (ctx == NULL) return 0; - ctx->name = NULL; - ctx->exec = NULL; - ctx->tryexec = NULL; + struct ctx_typ ctx = { + .name = NULL, + .exec = NULL, + .tryexec = NULL, + }; FILE* fd = fopen(fpath, "r"); if (fd == NULL) { - free(ctx); perror("fopen"); // NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) - (void)fprintf(stderr, "error opening file (r) '%s'\n", fpath); + (void)fprintf(stderr, "error opening file '%s' for read\n", fpath); return 0; } - int ret = read_desktop(fd, ctx, &cb); + int ret = read_desktop(fd, &ctx, &cb); if (ret < 0) { // any error - free(ctx); return 0; } (void)fclose(fd); // just add this to the list - if (ctx->name != NULL && ctx->exec != NULL) { - ctx->type = session_type; - vec_push(cb_sessions, ctx); + if (ctx.name != NULL && ctx.exec != NULL) { + struct session* this_session = malloc(sizeof(struct session)); + if (this_session == NULL) return 0; + + *this_session = (struct session){ + .name = ctx.name, + .exec = ctx.exec, + .tryexec = ctx.tryexec, + .type = session_type, + }; + + vec_push(cb_sessions, this_session); } return 0;