Skip to content

Commit a0f6d12

Browse files
author
Siva Chandra Reddy
committed
[libc][File] Fix a bug under fseek(..., SEEK_CUR).
Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D122284
1 parent b857a50 commit a0f6d12

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

libc/src/__support/File/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}_file.cpp)
2525
.file
2626
libc.include.errno
2727
libc.include.fcntl
28+
libc.include.stdio
2829
libc.include.sys_syscall
2930
libc.src.__support.OSUtil.osutil
3031
libc.src.errno.errno

libc/src/__support/File/file.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "src/__support/CPP/ArrayRef.h"
1212

1313
#include <errno.h>
14+
#include <stdio.h>
1415
#include <stdlib.h>
1516

1617
namespace __llvm_libc {
@@ -143,6 +144,11 @@ int File::seek(long offset, int whence) {
143144
err = true;
144145
return -1;
145146
}
147+
} else if (prev_op == FileOp::READ && whence == SEEK_CUR) {
148+
// More data could have been read out from the platform file than was
149+
// required. So, we have to adjust the offset we pass to platform seek
150+
// function. Note that read_limit >= pos is always true.
151+
offset -= (read_limit - pos);
146152
}
147153
pos = read_limit = 0;
148154
prev_op = FileOp::SEEK;

libc/test/src/__support/File/file_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,27 @@ TEST(LlvmLibcFileTest, ReadOnly) {
194194
ASSERT_EQ(f->close(), 0);
195195
}
196196

197+
TEST(LlvmLibcFileTest, ReadSeekCurAndRead) {
198+
const char initial_content[] = "1234567890987654321";
199+
constexpr size_t FILE_BUFFER_SIZE = sizeof(initial_content);
200+
char file_buffer[FILE_BUFFER_SIZE];
201+
StringFile *f = new_string_file(file_buffer, FILE_BUFFER_SIZE, 0, false, "r");
202+
f->reset_and_fill(initial_content, sizeof(initial_content));
203+
204+
constexpr size_t READ_SIZE = 5;
205+
char data[READ_SIZE];
206+
data[READ_SIZE - 1] = '\0';
207+
ASSERT_EQ(f->read(data, READ_SIZE - 1), READ_SIZE - 1);
208+
ASSERT_STREQ(data, "1234");
209+
ASSERT_EQ(f->seek(5, SEEK_CUR), 0);
210+
ASSERT_EQ(f->read(data, READ_SIZE - 1), READ_SIZE - 1);
211+
ASSERT_STREQ(data, "0987");
212+
ASSERT_EQ(f->seek(-5, SEEK_CUR), 0);
213+
ASSERT_EQ(f->read(data, READ_SIZE - 1), READ_SIZE - 1);
214+
ASSERT_STREQ(data, "9098");
215+
ASSERT_EQ(f->close(), 0);
216+
}
217+
197218
TEST(LlvmLibcFileTest, AppendOnly) {
198219
const char initial_content[] = "1234567890987654321";
199220
const char write_data[] = "append";

libc/test/src/__support/File/platform_file_test.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,32 @@ TEST(LlvmLibcPlatformFileTest, LargeFile) {
144144
ASSERT_EQ(file->close(), 0);
145145
}
146146

147+
TEST(LlvmLibcPlatformFileTest, ReadSeekCurAndRead) {
148+
constexpr char FILENAME[] = "testdata/read_seek_cur_and_read.test";
149+
File *file = __llvm_libc::openfile(FILENAME, "w");
150+
ASSERT_FALSE(file == nullptr);
151+
constexpr char CONTENT[] = "1234567890987654321";
152+
ASSERT_EQ(sizeof(CONTENT) - 1, file->write(CONTENT, sizeof(CONTENT) - 1));
153+
ASSERT_EQ(0, file->close());
154+
155+
file = __llvm_libc::openfile(FILENAME, "r");
156+
ASSERT_FALSE(file == nullptr);
157+
158+
constexpr size_t READ_SIZE = 5;
159+
char data[READ_SIZE];
160+
data[READ_SIZE - 1] = '\0';
161+
ASSERT_EQ(file->read(data, READ_SIZE - 1), READ_SIZE - 1);
162+
ASSERT_STREQ(data, "1234");
163+
ASSERT_EQ(file->seek(5, SEEK_CUR), 0);
164+
ASSERT_EQ(file->read(data, READ_SIZE - 1), READ_SIZE - 1);
165+
ASSERT_STREQ(data, "0987");
166+
ASSERT_EQ(file->seek(-5, SEEK_CUR), 0);
167+
ASSERT_EQ(file->read(data, READ_SIZE - 1), READ_SIZE - 1);
168+
ASSERT_STREQ(data, "9098");
169+
170+
ASSERT_EQ(file->close(), 0);
171+
}
172+
147173
TEST(LlvmLibcPlatformFileTest, IncorrectOperation) {
148174
constexpr char FILENAME[] = "testdata/incorrect_operation.test";
149175
char data[1] = {123};

0 commit comments

Comments
 (0)