diff --git a/winpr/libwinpr/clipboard/posix.c b/winpr/libwinpr/clipboard/posix.c index 2364f998d..76d8cb572 100644 --- a/winpr/libwinpr/clipboard/posix.c +++ b/winpr/libwinpr/clipboard/posix.c @@ -61,14 +61,13 @@ static struct posix_file* make_posix_file(const char* local_name, const WCHAR* r { struct posix_file* file = NULL; struct stat statbuf; - file = calloc(1, sizeof(*file)); + if (!file) return NULL; file->fd = -1; file->offset = 0; - file->local_name = _strdup(local_name); file->remote_name = _wcsdup(remote_name); @@ -84,14 +83,11 @@ static struct posix_file* make_posix_file(const char* local_name, const WCHAR* r file->is_directory = S_ISDIR(statbuf.st_mode); file->size = statbuf.st_size; - return file; - error: free(file->local_name); free(file->remote_name); free(file); - return NULL; } @@ -142,7 +138,6 @@ static BOOL decode_percent_encoded_byte(const char* str, const char* end, char* *value |= hex_to_dec(str[1], &valid); *value <<= 4; *value |= hex_to_dec(str[2], &valid); - return valid; } @@ -152,9 +147,9 @@ static char* decode_percent_encoded_string(const char* str, size_t len) char* next = NULL; const char* cur = str; const char* lim = str + len; - /* Percent decoding shrinks data length, so len bytes will be enough. */ buffer = calloc(len + 1, sizeof(char)); + if (!buffer) return NULL; @@ -180,10 +175,8 @@ static char* decode_percent_encoded_string(const char* str, size_t len) } return buffer; - error: free(buffer); - return NULL; } @@ -220,7 +213,6 @@ static WCHAR* convert_local_name_component_to_remote(const char* local_name) } return remote_name; - error: free(remote_name); return NULL; @@ -231,18 +223,16 @@ static char* concat_local_name(const char* dir, const char* file) size_t len_dir = 0; size_t len_file = 0; char* buffer = NULL; - len_dir = strlen(dir); len_file = strlen(file); - buffer = calloc(len_dir + 1 + len_file + 1, sizeof(char)); + if (!buffer) return NULL; memcpy(buffer, dir, len_dir * sizeof(char)); buffer[len_dir] = '/'; memcpy(buffer + len_dir + 1, file, len_file * sizeof(char)); - return buffer; } @@ -251,25 +241,23 @@ static WCHAR* concat_remote_name(const WCHAR* dir, const WCHAR* file) size_t len_dir = 0; size_t len_file = 0; WCHAR* buffer = NULL; - len_dir = _wcslen(dir); len_file = _wcslen(file); - buffer = calloc(len_dir + 1 + len_file + 1, sizeof(WCHAR)); + if (!buffer) return NULL; memcpy(buffer, dir, len_dir * sizeof(WCHAR)); buffer[len_dir] = L'\\'; memcpy(buffer + len_dir + 1, file, len_file * sizeof(WCHAR)); - return buffer; } static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files); static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* remote_dir_name, - const struct dirent* entry, wArrayList* files) + const struct dirent* entry, wArrayList* files) { BOOL result = FALSE; char* local_name = NULL; @@ -281,6 +269,7 @@ static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* return TRUE; remote_base_name = convert_local_name_component_to_remote(entry->d_name); + if (!remote_base_name) return FALSE; @@ -293,12 +282,11 @@ static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* free(remote_base_name); free(remote_name); free(local_name); - return result; } static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name, - DIR* dirp, wArrayList* files) + DIR* dirp, wArrayList* files) { /* * For some reason POSIX does not require readdir() to be thread-safe. @@ -313,16 +301,16 @@ static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHA * musl). We should not be breaking people's builds because of that, * so we do nothing and proceed with fingers crossed. */ - for (;;) { struct dirent* entry = NULL; - errno = 0; entry = readdir(dirp); + if (!entry) { int err = errno; + if (!err) break; @@ -338,14 +326,13 @@ static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHA } static BOOL add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name, - wArrayList* files) + wArrayList* files) { BOOL result = FALSE; DIR* dirp = NULL; - WLog_VRB(TAG, "adding directory: %s", local_name); - dirp = opendir(local_name); + if (!dirp) { int err = errno; @@ -360,6 +347,7 @@ static BOOL add_directory_contents_to_list(const char* local_name, const WCHAR* int err = errno; WLog_WARN(TAG, "failed to close directory: %s", strerror(err)); } + out: return result; } @@ -367,17 +355,15 @@ out: static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files) { struct posix_file* file = NULL; - WLog_VRB(TAG, "adding file: %s", local_name); - file = make_posix_file(local_name, remote_name); + if (!file) return FALSE; if (ArrayList_Add(files, file) < 0) { free_posix_file(file); - return FALSE; } @@ -413,22 +399,19 @@ static BOOL process_file_name(const char* local_name, wArrayList* files) BOOL result = FALSE; const char* base_name = NULL; WCHAR* remote_name = NULL; - /* * Start with the base name of the file. text/uri-list contains the * exact files selected by the user, and we want the remote files * to have names relative to that selection. */ base_name = get_basename(local_name); - remote_name = convert_local_name_component_to_remote(base_name); + if (!remote_name) return FALSE; result = add_file_to_list(local_name, remote_name, files); - free(remote_name); - return result; } @@ -436,7 +419,6 @@ static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files) { BOOL result = FALSE; char* name = NULL; - WLog_VRB(TAG, "processing URI: %.*s", uri_len, uri); if ((uri_len < strlen("file://")) || strncmp(uri, "file://", strlen("file://"))) @@ -446,13 +428,13 @@ static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files) } name = decode_percent_encoded_string(uri + strlen("file://"), uri_len - strlen("file://")); + if (!name) goto out; result = process_file_name(name, files); out: free(name); - return result; } @@ -462,9 +444,7 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) const char* lim = data + length; const char* start = NULL; const char* stop = NULL; - WLog_VRB(TAG, "processing URI list:\n%.*s", length, data); - ArrayList_Clear(files); /* @@ -478,9 +458,7 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) while (cur < lim) { BOOL comment = (*cur == '#'); - start = cur; - stop = cur; for (stop = cur; stop < lim; stop++) { @@ -490,14 +468,17 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) cur = stop + 2; else cur = stop + 1; + break; } + if (*stop == '\n') { cur = stop + 1; break; } } + if (stop == lim) cur = lim; @@ -512,10 +493,9 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files) } static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file, - FILEDESCRIPTOR* descriptor) + FILEDESCRIPTOR* descriptor) { size_t remote_len = 0; - descriptor->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_SHOWPROGRESSUI; if (file->is_directory) @@ -532,6 +512,7 @@ static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file, } remote_len = _wcslen(file->remote_name); + if (remote_len + 1 > ARRAYSIZE(descriptor->cFileName)) { WLog_ERR(TAG, "file name too long (%"PRIuz" characters)", remote_len); @@ -539,7 +520,6 @@ static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file, } memcpy(descriptor->cFileName, file->remote_name, remote_len * sizeof(WCHAR)); - return TRUE; } @@ -548,10 +528,9 @@ static FILEDESCRIPTOR* convert_local_file_list_to_filedescriptors(wArrayList* fi int i; int count = 0; FILEDESCRIPTOR* descriptors = NULL; - count = ArrayList_Count(files); - descriptors = calloc(count, sizeof(descriptors[0])); + if (!descriptors) goto error; @@ -564,15 +543,13 @@ static FILEDESCRIPTOR* convert_local_file_list_to_filedescriptors(wArrayList* fi } return descriptors; - error: free(descriptors); - return NULL; } static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 formatId, - const void* data, UINT32* pSize) + const void* data, UINT32* pSize) { FILEDESCRIPTOR* descriptors = NULL; @@ -586,13 +563,12 @@ static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 f return NULL; descriptors = convert_local_file_list_to_filedescriptors(clipboard->localFiles); + if (!descriptors) return NULL; *pSize = ArrayList_Count(clipboard->localFiles) * sizeof(FILEDESCRIPTOR); - clipboard->fileListSequenceNumber = clipboard->sequenceNumber; - return descriptors; } @@ -600,25 +576,25 @@ static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard) { UINT32 file_group_format_id; UINT32 local_file_format_id; - file_group_format_id = ClipboardRegisterFormat(clipboard, "FileGroupDescriptorW"); local_file_format_id = ClipboardRegisterFormat(clipboard, "text/uri-list"); + if (!file_group_format_id || !local_file_format_id) goto error; clipboard->localFiles = ArrayList_New(FALSE); + if (!clipboard->localFiles) goto error; ArrayList_Object(clipboard->localFiles)->fnObjectFree = free_posix_file; if (!ClipboardRegisterSynthesizer(clipboard, - local_file_format_id, file_group_format_id, - convert_uri_list_to_filedescriptors)) + local_file_format_id, file_group_format_id, + convert_uri_list_to_filedescriptors)) goto error_free_local_files; return TRUE; - error_free_local_files: ArrayList_Free(clipboard->localFiles); clipboard->localFiles = NULL; @@ -638,12 +614,11 @@ static UINT posix_file_get_size(const struct posix_file* file, INT64* size) } *size = statbuf.st_size; - return NO_ERROR; } static UINT posix_file_request_size(wClipboardDelegate* delegate, - const wClipboardFileSizeRequest* request) + const wClipboardFileSizeRequest* request) { UINT error = NO_ERROR; INT64 size = 0; @@ -656,6 +631,7 @@ static UINT posix_file_request_size(wClipboardDelegate* delegate, return ERROR_INVALID_STATE; file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex); + if (!file) return ERROR_INDEX_ABSENT; @@ -680,6 +656,7 @@ static UINT posix_file_read_open(struct posix_file* file) return NO_ERROR; file->fd = open(file->local_name, O_RDONLY); + if (file->fd < 0) { int err = errno; @@ -696,10 +673,8 @@ static UINT posix_file_read_open(struct posix_file* file) file->offset = 0; file->size = statbuf.st_size; - WLog_VRB(TAG, "open file %d -> %s", file->fd, file->local_name); WLog_VRB(TAG, "file %d size: %"PRIu64" bytes", file->fd, file->size); - return NO_ERROR; } @@ -715,7 +690,7 @@ static UINT posix_file_read_seek(struct posix_file* file, UINT64 offset) return NO_ERROR; WLog_VRB(TAG, "file %d force seeking to %"PRIu64", current %"PRIu64, file->fd, - offset, file->offset); + offset, file->offset); if (lseek(file->fd, offset, SEEK_SET) < 0) { @@ -728,14 +703,13 @@ static UINT posix_file_read_seek(struct posix_file* file, UINT64 offset) } static UINT posix_file_read_perform(struct posix_file* file, UINT32 size, - BYTE** actual_data, UINT32* actual_size) + BYTE** actual_data, UINT32* actual_size) { BYTE* buffer = NULL; ssize_t amount = 0; - WLog_VRB(TAG, "file %d request read %"PRIu32" bytes", file->fd, size); - buffer = malloc(size); + if (!buffer) { WLog_ERR(TAG, "failed to allocate %"PRIu32" buffer bytes", size); @@ -743,6 +717,7 @@ static UINT posix_file_read_perform(struct posix_file* file, UINT32 size, } amount = read(file->fd, buffer, size); + if (amount < 0) { int err = errno; @@ -753,15 +728,11 @@ static UINT posix_file_read_perform(struct posix_file* file, UINT32 size, *actual_data = buffer; *actual_size = amount; file->offset += amount; - WLog_VRB(TAG, "file %d actual read %"PRIu32" bytes (offset %"PRIu64")", file->fd, - amount, file->offset); - + amount, file->offset); return NO_ERROR; - error: free(buffer); - return ERROR_READ_FAULT; } @@ -779,6 +750,7 @@ static UINT posix_file_read_close(struct posix_file* file) int err = errno; WLog_WARN(TAG, "failed to close fd %d: %s", file->fd, strerror(err)); } + file->fd = -1; } @@ -786,31 +758,35 @@ static UINT posix_file_read_close(struct posix_file* file) } static UINT posix_file_get_range(struct posix_file* file, UINT64 offset, UINT32 size, - BYTE** actual_data, UINT32* actual_size) + BYTE** actual_data, UINT32* actual_size) { UINT error = NO_ERROR; - error = posix_file_read_open(file); + if (error) goto out; error = posix_file_read_seek(file, offset); + if (error) goto out; error = posix_file_read_perform(file, size, actual_data, actual_size); + if (error) goto out; error = posix_file_read_close(file); + if (error) goto out; + out: return error; } static UINT posix_file_request_range(wClipboardDelegate* delegate, - const wClipboardFileRangeRequest* request) + const wClipboardFileRangeRequest* request) { UINT error = 0; BYTE* data = NULL; @@ -825,6 +801,7 @@ static UINT posix_file_request_range(wClipboardDelegate* delegate, return ERROR_INVALID_STATE; file = ArrayList_GetItem(delegate->clipboard->localFiles, request->listIndex); + if (!file) return ERROR_INDEX_ABSENT; @@ -840,26 +817,29 @@ static UINT posix_file_request_range(wClipboardDelegate* delegate, WLog_WARN(TAG, "failed to report file range result: 0x%08X", error); free(data); - return NO_ERROR; } -static UINT dummy_file_size_success(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT64 fileSize) +static UINT dummy_file_size_success(wClipboardDelegate* delegate, + const wClipboardFileSizeRequest* request, UINT64 fileSize) { return ERROR_NOT_SUPPORTED; } -static UINT dummy_file_size_failure(wClipboardDelegate* delegate, const wClipboardFileSizeRequest* request, UINT errorCode) +static UINT dummy_file_size_failure(wClipboardDelegate* delegate, + const wClipboardFileSizeRequest* request, UINT errorCode) { return ERROR_NOT_SUPPORTED; } -static UINT dummy_file_range_success(wClipboardDelegate* delegate, const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size) +static UINT dummy_file_range_success(wClipboardDelegate* delegate, + const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size) { return ERROR_NOT_SUPPORTED; } -static UINT dummy_file_range_failure(wClipboardDelegate* delegate, const wClipboardFileRangeRequest* request, UINT errorCode) +static UINT dummy_file_range_failure(wClipboardDelegate* delegate, + const wClipboardFileRangeRequest* request, UINT errorCode) { return ERROR_NOT_SUPPORTED; } @@ -869,7 +849,6 @@ static void setup_delegate(wClipboardDelegate* delegate) delegate->ClientRequestFileSize = posix_file_request_size; delegate->ClipboardFileSizeSuccess = dummy_file_size_success; delegate->ClipboardFileSizeFailure = dummy_file_size_failure; - delegate->ClientRequestFileRange = posix_file_request_range; delegate->ClipboardFileRangeSuccess = dummy_file_range_success; delegate->ClipboardFileRangeFailure = dummy_file_range_failure; @@ -884,6 +863,5 @@ BOOL ClipboardInitPosixFileSubsystem(wClipboard* clipboard) return FALSE; setup_delegate(&clipboard->delegate); - return TRUE; }