diff --git a/src/rufus.c b/src/rufus.c index 8d22a9c4..ea0a87fe 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -22,6 +22,14 @@ #include #endif +// Temporary workaround for MinGW32 delay-loading +// See https://github.com/pbatard/rufus/pull/2513 as well as +// https://sourceware.org/bugzilla/show_bug.cgi?id=14339 +#if defined(__MINGW32__) +#undef DECLSPEC_IMPORT +#define DECLSPEC_IMPORT __attribute__((visibility("hidden"))) +#endif + #include #include #include diff --git a/src/rufus.rc b/src/rufus.rc index d81117d8..50716e2f 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 4.8.2241" +CAPTION "Rufus 4.8.2242" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -407,8 +407,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,8,2241,0 - PRODUCTVERSION 4,8,2241,0 + FILEVERSION 4,8,2242,0 + PRODUCTVERSION 4,8,2242,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -426,13 +426,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.8.2241" + VALUE "FileVersion", "4.8.2242" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2025 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.8.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.8.2241" + VALUE "ProductVersion", "4.8.2242" END END BLOCK "VarFileInfo" diff --git a/src/wimlib/dentry.c b/src/wimlib/dentry.c index 2666fa72..e7dac23e 100644 --- a/src/wimlib/dentry.c +++ b/src/wimlib/dentry.c @@ -490,7 +490,10 @@ calculate_dentry_full_path(struct wim_dentry *dentry) d = d->d_parent; /* assumes d == d->d_parent for root */ } while (!dentry_is_root(d)); - utf16lechar* ubuf = alloca(ulen * sizeof(utf16lechar)); + // +1 to keep Coverity happy + utf16lechar *ubuf = alloca((ulen + 1) * sizeof(utf16lechar)); + if (!ubuf) + return WIMLIB_ERR_NOMEM; utf16lechar *p = &ubuf[ulen]; d = dentry; @@ -518,7 +521,8 @@ calculate_dentry_full_path(struct wim_dentry *dentry) tchar * dentry_full_path(struct wim_dentry *dentry) { - calculate_dentry_full_path(dentry); + if (calculate_dentry_full_path(dentry)) + return NULL; return dentry->d_full_path; } diff --git a/src/wimlib/extract.c b/src/wimlib/extract.c index ecb558c4..5c18da5b 100644 --- a/src/wimlib/extract.c +++ b/src/wimlib/extract.c @@ -390,6 +390,7 @@ create_temporary_file(struct filedes *fd_ret, tchar **name_ret) #ifdef _WIN32 retry: + // coverity[secure_temp] name = _wtempnam(NULL, L"wimlib"); if (!name) { ERROR_WITH_ERRNO("Failed to create temporary filename"); diff --git a/src/wimlib/integrity.c b/src/wimlib/integrity.c index 1f022123..320e51e6 100644 --- a/src/wimlib/integrity.c +++ b/src/wimlib/integrity.c @@ -76,6 +76,8 @@ calculate_chunk_sha1(struct filedes *in_fd, size_t this_chunk_size, "integrity checksums"); return ret; } + // I have no idea what Coverity is hallucinating with here... + // coverity[overrun-call] sha1_update(&ctx, buf, bytes_to_read); bytes_remaining -= bytes_to_read; offset += bytes_to_read; diff --git a/src/wimlib/lcpit_matchfinder.c b/src/wimlib/lcpit_matchfinder.c index 33dfb701..fce6073a 100644 --- a/src/wimlib/lcpit_matchfinder.c +++ b/src/wimlib/lcpit_matchfinder.c @@ -587,6 +587,7 @@ bool lcpit_matchfinder_init(struct lcpit_matchfinder *mf, size_t max_bufsize, u32 min_match_len, u32 nice_match_len) { + // coverity[dead_error_condition] if (lcpit_matchfinder_get_needed_memory(max_bufsize) > SIZE_MAX) return false; if (max_bufsize > MAX_HUGE_BUFSIZE - PREFETCH_SAFETY) diff --git a/src/wimlib/lzms_compress.c b/src/wimlib/lzms_compress.c index 72e18f74..74e6d298 100644 --- a/src/wimlib/lzms_compress.c +++ b/src/wimlib/lzms_compress.c @@ -1971,8 +1971,10 @@ begin: if (next_item_idx < 0) break; if (next_item_idx == 0) + // coverity[assigned_value] item_to_take = cur_node->item; else + // coverity[assigned_value] item_to_take = cur_node->extra_items[next_item_idx - 1]; --next_item_idx; } diff --git a/src/wimlib/lzx_compress.c b/src/wimlib/lzx_compress.c index 69039b09..89dfade0 100644 --- a/src/wimlib/lzx_compress.c +++ b/src/wimlib/lzx_compress.c @@ -1452,6 +1452,7 @@ lzx_walk_item_list(struct lzx_compressor *c, u32 block_size, bool is_16_bit, /* Tally/record a match. */ matchlen = item & OPTIMUM_LEN_MASK; adjusted_offset = item >> OPTIMUM_OFFSET_SHIFT; + // coverity[overrun-call] mainsym = lzx_tally_main_and_lensyms(c, matchlen, adjusted_offset, is_16_bit); diff --git a/src/wimlib/sha1.c b/src/wimlib/sha1.c index 14b68239..1a9486b0 100644 --- a/src/wimlib/sha1.c +++ b/src/wimlib/sha1.c @@ -610,7 +610,9 @@ sha1_final(struct sha1_ctx *ctx, u8 hash[SHA1_HASH_SIZE]) ctx->buffer[buffered++] = 0x80; if (buffered > SHA1_BLOCK_SIZE - 8) { - memset(&ctx->buffer[buffered], 0, SHA1_BLOCK_SIZE - buffered); + // Keep Coverity happy + if (buffered != SHA1_BLOCK_SIZE) + memset(&ctx->buffer[buffered], 0, SHA1_BLOCK_SIZE - buffered); sha1_blocks(ctx->h, ctx->buffer, 1); buffered = 0; } diff --git a/src/wimlib/wim.c b/src/wimlib/wim.c index f1a5fa5c..287d3056 100644 --- a/src/wimlib/wim.c +++ b/src/wimlib/wim.c @@ -1044,8 +1044,8 @@ wimlib_get_version_string(void) return T(PACKAGE_VERSION); } +static volatile uint16_t lib_initialization_mutex = 0; static bool lib_initialized = false; -static struct mutex lib_initialization_mutex = MUTEX_INITIALIZER; /* API function documented in wimlib.h */ WIMLIBAPI int @@ -1053,11 +1053,13 @@ wimlib_global_init(int init_flags) { int ret = 0; - if (lib_initialized) - goto out; - - mutex_init(&lib_initialization_mutex); - mutex_lock(&lib_initialization_mutex); + // Non problematic init/cleanup mutex (Windows only) to keep static + // analysers happy. Only one thread at a time can run the code between + // initial InterlockedIncrement and ending InterlockedDecrement. + while (InterlockedIncrement16(&lib_initialization_mutex) >= 2) { + InterlockedDecrement16(&lib_initialization_mutex); + Sleep(100); + } if (lib_initialized) goto out_unlock; @@ -1095,8 +1097,7 @@ wimlib_global_init(int init_flags) lib_initialized = true; ret = 0; out_unlock: - mutex_unlock(&lib_initialization_mutex); -out: + InterlockedDecrement16(&lib_initialization_mutex); return ret; } @@ -1104,10 +1105,10 @@ out: WIMLIBAPI void wimlib_global_cleanup(void) { - if (!lib_initialized) - return; - - mutex_lock(&lib_initialization_mutex); + while (InterlockedIncrement16(&lib_initialization_mutex) >= 2) { + InterlockedDecrement16(&lib_initialization_mutex); + Sleep(100); + } if (!lib_initialized) goto out_unlock; @@ -1120,6 +1121,5 @@ wimlib_global_cleanup(void) lib_initialized = false; out_unlock: - mutex_unlock(&lib_initialization_mutex); - mutex_destroy(&lib_initialization_mutex); + InterlockedDecrement16(&lib_initialization_mutex); } diff --git a/src/wimlib/wimboot.c b/src/wimlib/wimboot.c index 115a5699..71580397 100644 --- a/src/wimlib/wimboot.c +++ b/src/wimlib/wimboot.c @@ -809,6 +809,7 @@ update_wimoverlay_manually(const wchar_t *drive, const wchar_t *wim_path, if (ret) goto out; + // coverity[tainted_data] ret = prepare_wimoverlay_dat(old_contents, wim_path, wim_guid, image, &new_contents, &new_contents_size, &new_data_source_id); diff --git a/src/wimlib/wimlib/compiler.h b/src/wimlib/wimlib/compiler.h index 6ad165ad..5a74fbf3 100644 --- a/src/wimlib/wimlib/compiler.h +++ b/src/wimlib/wimlib/compiler.h @@ -234,14 +234,15 @@ uint32_t __inline __builtin_ctz(uint32_t value) unsigned long trailing_zero = 0; if (_BitScanForward(&trailing_zero, value)) return trailing_zero; - return 32; + // Undefined behaviour => return 0 to appease static analyzers + return 0; } uint32_t __inline __builtin_clz(uint32_t value) { unsigned long leading_zero = 0; if (_BitScanReverse(&leading_zero, value)) return 31 - leading_zero; - return 32; + return 0; } #if defined(_M_X64) || defined(_M_ARM64) uint32_t __inline __builtin_clzll(uint64_t value) @@ -249,20 +250,20 @@ uint32_t __inline __builtin_clzll(uint64_t value) unsigned long leading_zero = 0; if (_BitScanReverse64(&leading_zero, value)) return 63 - leading_zero; - return 64; + return 0; } uint32_t __inline __builtin_ctzll(uint64_t value) { unsigned long trailing_zero = 0; if (_BitScanForward64(&trailing_zero, value)) return trailing_zero; - return 64; + return 0; } #else uint32_t __inline __builtin_clzll(uint64_t value) { if (value == 0) - return 64; + return 0; uint32_t msh = (uint32_t)(value >> 32); uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); if (msh != 0) @@ -272,7 +273,7 @@ uint32_t __inline __builtin_clzll(uint64_t value) uint32_t __inline __builtin_ctzll(uint64_t value) { if (value == 0) - return 64; + return 0; uint32_t msh = (uint32_t)(value >> 32); uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); if (msh != 0) diff --git a/src/wimlib/win32_capture.c b/src/wimlib/win32_capture.c index 895fcf7f..0a37e684 100644 --- a/src/wimlib/win32_capture.c +++ b/src/wimlib/win32_capture.c @@ -2800,10 +2800,8 @@ generate_wim_structures_recursive(struct wim_dentry **root_ret, root->d_short_name_nbytes = nbytes; } - if (inode->i_nlink > 1) { /* Already seen this inode? */ - ret = 0; + if (inode->i_nlink > 1) /* Already seen this inode? */ goto out_progress; - } /* The file attributes and timestamps were cached from the MFT. */ inode->i_attributes = ni->attributes; diff --git a/src/wimlib/win32_vss.c b/src/wimlib/win32_vss.c index 8ab69a3b..9ee346a5 100644 --- a/src/wimlib/win32_vss.c +++ b/src/wimlib/win32_vss.c @@ -215,7 +215,7 @@ struct IVssBackupComponentsVTable { *----------------------------------------------------------------------------*/ static bool vss_initialized; -static struct mutex vss_initialization_mutex = MUTEX_INITIALIZER; +static volatile uint16_t vss_initialization_mutex = 0; /* vssapi.dll */ static HANDLE hVssapi; @@ -282,35 +282,47 @@ err: static bool vss_global_init(void) { - if (vss_initialized) - return true; + bool ret = true; - mutex_lock(&vss_initialization_mutex); - if (!vss_initialized) - vss_initialized = vss_global_init_impl(); - mutex_unlock(&vss_initialization_mutex); + while (InterlockedIncrement16(&vss_initialization_mutex) >= 2) { + InterlockedDecrement16(&vss_initialization_mutex); + Sleep(100); + } if (vss_initialized) - return true; - ERROR("The Volume Shadow Copy Service (VSS) API could not be " - "initialized."); - return false; + goto out_unlock; + + vss_initialized = vss_global_init_impl(); + + if (!vss_initialized) { + ERROR("The Volume Shadow Copy Service (VSS) API could not be " + "initialized."); + ret = false; + } + +out_unlock: + InterlockedDecrement16(&vss_initialization_mutex); + return ret; } void vss_global_cleanup(void) { - if (!vss_initialized) - return; - - mutex_lock(&vss_initialization_mutex); - if (vss_initialized) { - (*func_CoUninitialize)(); - FreeLibrary(hOle32); - FreeLibrary(hVssapi); - vss_initialized = false; + while (InterlockedIncrement16(&vss_initialization_mutex) >= 2) { + InterlockedDecrement16(&vss_initialization_mutex); + Sleep(100); } - mutex_unlock(&vss_initialization_mutex); + + if (!vss_initialized) + goto out_unlock; + + (*func_CoUninitialize)(); + FreeLibrary(hOle32); + FreeLibrary(hVssapi); + vss_initialized = false; + +out_unlock: + InterlockedDecrement16(&vss_initialization_mutex); } /*----------------------------------------------------------------------------* diff --git a/src/wimlib/xmlproc.c b/src/wimlib/xmlproc.c index 86e29e4f..121eb418 100644 --- a/src/wimlib/xmlproc.c +++ b/src/wimlib/xmlproc.c @@ -644,7 +644,8 @@ xml_parse_document(const tchar *p, struct xml_node **doc_ret) int ret; struct xml_node *doc; - skip_string(&p, BYTE_ORDER_MARK); + // Keep static analysers happy since we don't care about returned value. + (void)skip_string(&p, BYTE_ORDER_MARK); if (!skip_misc(&p)) return WIMLIB_ERR_XML; ret = parse_element(&p, NULL, 0, &doc); diff --git a/src/xml.c b/src/xml.c index b344bb73..f26a99db 100644 --- a/src/xml.c +++ b/src/xml.c @@ -237,7 +237,7 @@ char *ezxml_decode(char *s, char **ent, char t) if (ent[b++]) { // found a match if ((c = (long)strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) { - l = (d = (long)(s - r)) + c + (long)strlen(e); // new length + l = (d = (long)(s - r)) + c + (long)(e ? strlen(e) : 0); // new length r = (r == m) ? strcpy(malloc(l), r) : _realloc(r, l); e = strchr((s = r + d), ';'); // fix up pointers } @@ -683,8 +683,7 @@ ezxml_t ezxml_parse_fd(int fd) size_t l; void *m; - if (fd < 0) return NULL; - fstat(fd, &st); + if (fd < 0 || fstat(fd, &st)) return NULL; #ifndef EZXML_NOMMAP l = (st.st_size + sysconf(_SC_PAGESIZE) - 1) & ~(sysconf(_SC_PAGESIZE) -1); @@ -698,6 +697,7 @@ ezxml_t ezxml_parse_fd(int fd) else { // mmap failed, read file into memory #endif // EZXML_NOMMAP l = (long)_read(fd, m = malloc((size_t)st.st_size), (unsigned int)st.st_size); + if (l < 0) { free(m); return NULL; }; root = (ezxml_root_t)ezxml_parse_str(m, l); if (!root) { free(m); return NULL; }; root->len = -1; // so we know to free s in ezxml_free() @@ -719,7 +719,7 @@ ezxml_t ezxml_parse_file(const char *file) // Encodes ampersand sequences appending the results to *dst, reallocating *dst // if length excedes max. a is non-zero for attribute encoding. Returns *dst -char *ezxml_ampencode(const char *s, size_t len, char **dst, size_t *dlen, +char *ezxml_ampencode(const char *s, ssize_t len, char **dst, size_t *dlen, size_t *max, short a) { const char *e;