Skip to content

Commit

Permalink
FMap: Windows & 32bit compatibility fix for Rust interface
Browse files Browse the repository at this point in the history
The fmap structure has some stuff that differs in size in memory between
Linux and Windows, and between 32bit and 64bit architectures.

Notably, `time_t` appears to be defined by the Rust bindgen module as
`ulong` which may be either 8 bytes or 4 bytes, depending architecture
(thanks, C). To resolve this, we'll store time as a uint64_t instead.

The other problem in the fmap structure is the windows file and map
handles should always be exist, and may only be used in Windows, for
consistency in sizing of the structure.
  • Loading branch information
micahsnyder committed Dec 7, 2023
1 parent 31fc05e commit 461df01
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 36 deletions.
36 changes: 18 additions & 18 deletions libclamav/fmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha
m = cl_fmap_open_handle((void *)(ssize_t)fd, offset, len, pread_cb, 1);
if (!m)
return NULL;
m->mtime = st.st_mtime;
m->mtime = (uint64_t)st.st_mtime;

if (NULL != name) {
m->name = cli_strdup(name);
Expand All @@ -152,8 +152,8 @@ static void unmap_win32(fmap_t *m)
if (NULL != m->data) {
UnmapViewOfFile(m->data);
}
if (NULL != m->mh) {
CloseHandle(m->mh);
if (NULL != m->windows_map_handle) {
CloseHandle(m->windows_map_handle);
}
if (NULL != m->name) {
free(m->name);
Expand All @@ -169,8 +169,8 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha
STATBUF st;
fmap_t *m = NULL;
const void *data;
HANDLE fh;
HANDLE mh;
HANDLE windows_file_handle;
HANDLE windows_map_handle;

*empty = 0;
if (FSTAT(fd, &st)) {
Expand All @@ -194,30 +194,30 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha

pages = fmap_align_items(len, pgsz);

if ((fh = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) {
if ((windows_file_handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) {
cli_errmsg("fmap: cannot get a valid handle for descriptor %d\n", fd);
return NULL;
}
if (!(mh = CreateFileMapping(fh, NULL, PAGE_READONLY, (DWORD)((len >> 31) >> 1), (DWORD)len, NULL))) {
if (!(windows_map_handle = CreateFileMapping(windows_file_handle, NULL, PAGE_READONLY, (DWORD)((len >> 31) >> 1), (DWORD)len, NULL))) {
cli_errmsg("fmap: cannot create a map of descriptor %d\n", fd);
return NULL;
}
if (!(data = MapViewOfFile(mh, FILE_MAP_READ, (DWORD)((offset >> 31) >> 1), (DWORD)(offset), len))) {
if (!(data = MapViewOfFile(windows_map_handle, FILE_MAP_READ, (DWORD)((offset >> 31) >> 1), (DWORD)(offset), len))) {
cli_errmsg("fmap: cannot map file descriptor %d\n", fd);
CloseHandle(mh);
CloseHandle(windows_map_handle);
return NULL;
}
if (!(m = cl_fmap_open_memory(data, len))) {
cli_errmsg("fmap: cannot allocate fmap_t\n", fd);
UnmapViewOfFile(data);
CloseHandle(mh);
CloseHandle(windows_map_handle);
return NULL;
}
m->handle = (void *)(size_t)fd;
m->handle_is_fd = 1; /* This is probably(?) needed so `fmap_fd()` can return the file descriptor. */
m->fh = fh;
m->mh = mh;
m->unmap = unmap_win32;
m->handle = (void *)(size_t)fd;
m->handle_is_fd = true; /* This is probably(?) needed so `fmap_fd()` can return the file descriptor. */
m->windows_file_handle = (void *)windows_file_handle;
m->windows_map_handle = (void *)windows_map_handle;
m->unmap = unmap_win32;

if (NULL != name) {
m->name = cli_strdup(name);
Expand Down Expand Up @@ -416,7 +416,7 @@ extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
}
m->handle = handle;
m->pread_cb = pread_cb;
m->aging = use_aging;
m->aging = use_aging != 0 ? true : false;
m->offset = offset;
m->nested_offset = 0;
m->len = len; /* m->nested_offset + m->len = m->real_len */
Expand All @@ -430,7 +430,7 @@ extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
m->need_offstr = handle_need_offstr;
m->gets = handle_gets;
m->unneed_off = handle_unneed_off;
m->handle_is_fd = 1;
m->handle_is_fd = true;
m->have_md5 = false;
m->have_sha1 = false;
m->have_sha256 = false;
Expand Down Expand Up @@ -587,7 +587,7 @@ static int fmap_readpage(fmap_t *m, uint64_t first_page, uint64_t count, uint64_
cli_warnmsg("fmap_readpage: fstat failed: %s\n", errtxt);
return 1;
}
if (m->mtime != st.st_mtime) {
if (m->mtime != (uint64_t)st.st_mtime) {
cli_warnmsg("fmap_readpage: file changed as we read it\n");
return 1;
}
Expand Down
28 changes: 13 additions & 15 deletions libclamav/fmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ struct cl_fmap {
const void *data;

/* internal */
time_t mtime;
uint64_t mtime;
uint64_t pages;
uint64_t pgsz;
uint64_t paged;
uint16_t aging;
bool dont_cache_flag; /** indicates if we should not cache scan results for this fmap. Used if limits exceeded */
uint16_t handle_is_fd; /** non-zero if map->handle is an fd. */
size_t offset; /** file offset representing start of original fmap, if the fmap created reading from a file starting at offset other than 0 */
size_t nested_offset; /** offset from start of original fmap (data) for nested scan. 0 for orig fmap. */
size_t real_len; /** len from start of original fmap (data) to end of current (possibly nested) map. */
/* real_len == nested_offset + len.
real_len is needed for nested maps because we only reference the original mapping data.
We convert caller's fmap offsets & lengths to real data offsets using nested_offset & real_len. */
bool aging; /** indicates if we should age off memory mapped pages */
bool dont_cache_flag; /** indicates if we should not cache scan results for this fmap. Used if limits exceeded */
bool handle_is_fd; /** non-zero if map->handle is an fd. */
size_t offset; /** file offset representing start of original fmap, if the fmap created reading from a file starting at offset other than 0 */
size_t nested_offset; /** offset from start of original fmap (data) for nested scan. 0 for orig fmap. */
size_t real_len; /** len from start of original fmap (data) to end of current (possibly nested) map. */
/* real_len == nested_offset + len.
real_len is needed for nested maps because we only reference the original mapping data.
We convert caller's fmap offsets & lengths to real data offsets using nested_offset & real_len. */

/* external */
size_t len; /** length of data from nested_offset, accessible via current fmap */
Expand All @@ -82,10 +82,8 @@ struct cl_fmap {
const void *(*need_offstr)(fmap_t *, size_t at, size_t len_hint);
const void *(*gets)(fmap_t *, char *dst, size_t *at, size_t max_len);
void (*unneed_off)(fmap_t *, size_t at, size_t len);
#ifdef _WIN32
HANDLE fh;
HANDLE mh;
#endif
void *windows_file_handle;
void *windows_map_handle;
bool have_md5;
unsigned char md5[CLI_HASHLEN_MD5];
bool have_sha1;
Expand Down Expand Up @@ -424,7 +422,7 @@ cl_error_t fmap_dump_to_file(fmap_t *map, const char *filepath, const char *tmpd
* @brief Return the open file descriptor for the fmap (if available).
*
* This function will only provide the file descriptor if the fmap handle is set,
* and if the handle is in fact a file descriptor (handle_is_fd != 0).
* and if the handle is in fact a file descriptor (handle_is_fd == true).
*
* @param m The fmap.
* @return int The file descriptor, or -1 if not available.
Expand Down
9 changes: 6 additions & 3 deletions libclamav_rust/src/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,14 +268,15 @@ pub struct cl_fmap {
pub handle: *mut ::std::os::raw::c_void,
pub pread_cb: clcb_pread,
pub data: *const ::std::os::raw::c_void,
pub mtime: time_t,
pub mtime: u64,
pub pages: u64,
pub pgsz: u64,
pub paged: u64,
pub aging: u16,
pub aging: bool,
#[doc = " indicates if we should age off memory mapped pages"]
pub dont_cache_flag: bool,
#[doc = " indicates if we should not cache scan results for this fmap. Used if limits exceeded"]
pub handle_is_fd: u16,
pub handle_is_fd: bool,
#[doc = " non-zero if map->handle is an fd."]
pub offset: usize,
#[doc = " file offset representing start of original fmap, if the fmap created reading from a file starting at offset other than 0"]
Expand Down Expand Up @@ -311,6 +312,8 @@ pub struct cl_fmap {
>,
pub unneed_off:
::std::option::Option<unsafe extern "C" fn(arg1: *mut fmap_t, at: usize, len: usize)>,
pub windows_file_handle: *mut ::std::os::raw::c_void,
pub windows_map_handle: *mut ::std::os::raw::c_void,
pub have_md5: bool,
pub md5: [::std::os::raw::c_uchar; 16usize],
pub have_sha1: bool,
Expand Down

0 comments on commit 461df01

Please sign in to comment.