diff -Naur a/programs/util.c b/programs/util.c --- a/programs/util.c 2023-03-30 14:37:28.909949603 +0800 +++ b/programs/util.c 2023-03-30 14:35:20.772468440 +0800 @@ -870,30 +870,27 @@ static char* mallocAndJoin2Dir(const char *dir1, const char *dir2) { - const size_t dir1Size = strlen(dir1); - const size_t dir2Size = strlen(dir2); - char *outDirBuffer, *buffer, trailingChar; - assert(dir1 != NULL && dir2 != NULL); - outDirBuffer = (char *) malloc(dir1Size + dir2Size + 2); - CONTROL(outDirBuffer != NULL); - - memcpy(outDirBuffer, dir1, dir1Size); - outDirBuffer[dir1Size] = '\0'; + { const size_t dir1Size = strlen(dir1); + const size_t dir2Size = strlen(dir2); + char *outDirBuffer, *buffer; + outDirBuffer = (char *) malloc(dir1Size + dir2Size + 2); + CONTROL(outDirBuffer != NULL); + memcpy(outDirBuffer, dir1, dir1Size); + outDirBuffer[dir1Size] = '\0'; + if (dir2[0] == '.') + return outDirBuffer; + buffer = outDirBuffer + dir1Size; + if (dir1Size > 0 && *(buffer - 1) != PATH_SEP) { + *buffer = PATH_SEP; + buffer++; + } + memcpy(buffer, dir2, dir2Size); + buffer[dir2Size] = '\0'; - if (dir2[0] == '.') return outDirBuffer; - - buffer = outDirBuffer + dir1Size; - trailingChar = *(buffer - 1); - if (trailingChar != PATH_SEP) { - *buffer = PATH_SEP; - buffer++; } - memcpy(buffer, dir2, dir2Size); - buffer[dir2Size] = '\0'; - return outDirBuffer; } /* this function will return NULL if input srcFileName is not valid name for mirrored output path */ diff -Naur a/programs/zstdcli.c b/programs/zstdcli.c --- a/programs/zstdcli.c 2023-03-30 14:37:28.909949603 +0800 +++ b/programs/zstdcli.c 2023-03-30 14:35:20.772468440 +0800 @@ -990,7 +990,14 @@ if (longCommandWArg(&argument, "--stream-size=")) { streamSrcSize = readSizeTFromChar(&argument); continue; } if (longCommandWArg(&argument, "--target-compressed-block-size=")) { targetCBlockSize = readSizeTFromChar(&argument); continue; } if (longCommandWArg(&argument, "--size-hint=")) { srcSizeHint = readSizeTFromChar(&argument); continue; } - if (longCommandWArg(&argument, "--output-dir-flat")) { NEXT_FIELD(outDirName); continue; } + if (longCommandWArg(&argument, "--output-dir-flat")) { + NEXT_FIELD(outDirName); + if (strlen(outDirName) == 0) { + DISPLAY("error: output dir cannot be empty string (did you mean to pass '.' instead?)\n"); + CLEAN_RETURN(1); + } + continue; + } #ifdef ZSTD_MULTITHREAD if (longCommandWArg(&argument, "--auto-threads")) { const char* threadDefault = NULL; @@ -1001,7 +1008,14 @@ } #endif #ifdef UTIL_HAS_MIRRORFILELIST - if (longCommandWArg(&argument, "--output-dir-mirror")) { NEXT_FIELD(outMirroredDirName); continue; } + if (longCommandWArg(&argument, "--output-dir-mirror")) { + NEXT_FIELD(outMirroredDirName); + if (strlen(outMirroredDirName) == 0) { + DISPLAY("error: output dir cannot be empty string (did you mean to pass '.' instead?)\n"); + CLEAN_RETURN(1); + } + continue; + } #endif #ifndef ZSTD_NOTRACE if (longCommandWArg(&argument, "--trace")) { char const* traceFile; NEXT_FIELD(traceFile); TRACE_enable(traceFile); continue; }