Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 39 additions & 23 deletions src/io.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
// Copyright 2020 Joe Drago. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause

#if !defined(_WIN32)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking cygwin/mingw might support this, but they should also support the windows specifics you added. We can test this if the toolchains are covered by the presubmit.

// Ensure off_t is 64 bits.
#undef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif

#include "avif/internal.h"

#include <limits.h>
#include <stdio.h>
#include <string.h>

#if defined(_WIN32)
// Windows uses _fseeki64 / _ftelli64 for large file support
typedef __int64 avif_off_t;

static int avif_fseeko(FILE * stream, avif_off_t offset, int whence)
{
return _fseeki64(stream, offset, whence);
}

static avif_off_t avif_ftello(FILE * stream)
{
return _ftelli64(stream);
}
#else
// POSIX large file support
typedef off_t avif_off_t;

static int avif_fseeko(FILE * stream, avif_off_t offset, int whence)
{
return fseeko(stream, offset, whence);
}

static avif_off_t avif_ftello(FILE * stream)
{
return ftello(stream);
}
#endif

void avifIODestroy(avifIO * io)
{
if (io && io->destroy) {
Expand Down Expand Up @@ -104,13 +138,13 @@ static avifResult avifIOFileReaderRead(struct avifIO * io, uint32_t readFlags, u
}

if (size > 0) {
if (offset > LONG_MAX) {
if (offset > INT64_MAX) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

James: This is the only weakness of this pull request. There is no symbolic constant such as OFF_MAX for the maximum value of the off_t type. So here we assume without checking that off_t is 64 bits. (off_t is a signed integer by definition.)

This check ensures that it is safe to cast offset to avif_off_t at line 147.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing common anyway. I see gcc/clang report #define __OFF_T_MATCHES_OFF64_T 1. I wonder if it's worth adding a compile time assert in the posix path for sizeof(off_t) == 8?

return AVIF_RESULT_IO_ERROR;
}
if (reader->buffer.size < size) {
AVIF_CHECKRES(avifRWDataRealloc(&reader->buffer, size));
}
if (fseek(reader->f, (long)offset, SEEK_SET) != 0) {
if (avif_fseeko(reader->f, (avif_off_t)offset, SEEK_SET) != 0) {
return AVIF_RESULT_IO_ERROR;
}
size_t bytesRead = fread(reader->buffer.data, 1, size, reader->f);
Expand Down Expand Up @@ -142,37 +176,19 @@ avifIO * avifIOCreateFileReader(const char * filename)
return NULL;
}

#if defined(_WIN32)
// Windows uses _fseeki64 / _ftelli64 for large file support
if (_fseeki64(f, 0, SEEK_END) != 0) {
if (avif_fseeko(f, 0, SEEK_END) != 0) {
fclose(f);
return NULL;
}
__int64 fileSize = _ftelli64(f);
avif_off_t fileSize = avif_ftello(f);
if (fileSize < 0) {
fclose(f);
return NULL;
}
if (_fseeki64(f, 0, SEEK_SET) != 0) {
fclose(f);
return NULL;
}
#else
// POSIX large file support
if (fseeko(f, 0, SEEK_END) != 0) {
if (avif_fseeko(f, 0, SEEK_SET) != 0) {
fclose(f);
return NULL;
}
off_t fileSize = ftello(f);
if (fileSize < 0) {
fclose(f);
return NULL;
}
if (fseeko(f, 0, SEEK_SET) != 0) {
fclose(f);
return NULL;
}
#endif

avifIOFileReader * reader = (avifIOFileReader *)avifAlloc(sizeof(avifIOFileReader));
if (!reader) {
Expand Down
Loading