Skip to content

Commit

Permalink
Fix usage of 'getline' function from standard library (Github issue #2)
Browse files Browse the repository at this point in the history
when getline() is inlined by the compiler, it resorts to using and linking against
the __getdelim function from the standard library.
However only the getdelim function was covered by pdwfs, not the __getdelim

Besides no tests were actually covering getline and getdelim...bad, very bad.
  • Loading branch information
JCapul committed Nov 19, 2019
1 parent 2d4e3b5 commit a970559
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 8 deletions.
6 changes: 3 additions & 3 deletions src/c/libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static int (*ptr_statvfs)(const char *pathname, struct statvfs *buf) = NULL;
static int (*ptr_statvfs64)(const char *pathname, struct statvfs64 *buf) = NULL;
static int (*ptr_fstatvfs)(int fd, struct statvfs *buf) = NULL;
static int (*ptr_fstatvfs64)(int fd, struct statvfs64 *buf) = NULL;
static ssize_t (*ptr_getdelim)(char **buf, size_t *bufsiz, int delimiter, FILE *fp) = NULL;
static ssize_t (*ptr___getdelim)(char **buf, size_t *bufsiz, int delimiter, FILE *fp) = NULL;
static ssize_t (*ptr_getline)(char **lineptr, size_t *n, FILE *stream) = NULL;
static DIR* (*ptr_opendir)(const char* path) = NULL;
static int (*ptr_feof)(FILE *stream) = NULL;
Expand Down Expand Up @@ -488,8 +488,8 @@ int libc_fstatvfs64(int fd, struct statvfs64 *buf) {
CALL_NEXT(fstatvfs64, fd, buf)
}

ssize_t libc_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) {
CALL_NEXT(getdelim, buf, bufsiz, delimiter, fp)
ssize_t libc___getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) {
CALL_NEXT(__getdelim, buf, bufsiz, delimiter, fp)
}

ssize_t libc_getline(char **buf, size_t *bufsiz, FILE *stream) {
Expand Down
2 changes: 1 addition & 1 deletion src/c/libc.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ int libc_statvfs(const char *pathname, struct statvfs *buf);
int libc_statvfs64(const char *pathname, struct statvfs64 *buf);
int libc_fstatvfs(int fd, struct statvfs *buf);
int libc_fstatvfs64(int fd, struct statvfs64 *buf);
ssize_t libc_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp);
ssize_t libc___getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp);
ssize_t libc_getline(char **buf, size_t *bufsiz, FILE *stream);
DIR* libc_opendir(const char* path);
int libc_feof(FILE *stream);
Expand Down
9 changes: 5 additions & 4 deletions src/c/pdwfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1110,16 +1110,15 @@ int fstatvfs64(int fd, struct statvfs64 *buf) {
NOT_IMPLEMENTED("fstatvfs64")
}

ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *stream) {
TRACE("intercepting getdelim(buf=%p, bufsiz=%p, delimiter=%d, stream=%p)\n", buf, bufsiz, delimiter, stream)
ssize_t __getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *stream) {
TRACE("intercepting __getdelim(buf=%p, bufsiz=%p, delimiter=%d, stream=%p)\n", buf, bufsiz, delimiter, stream)

if STREAM_NOT_MANAGED(stream) {
return libc_getdelim(buf, bufsiz, delimiter, stream);
return libc___getdelim(buf, bufsiz, delimiter, stream);
}

char *ptr, *eptr;


if (*buf == NULL || *bufsiz == 0) {
*bufsiz = BUFSIZ;
if ((*buf = malloc(*bufsiz)) == NULL)
Expand Down Expand Up @@ -1153,6 +1152,8 @@ ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *stream) {
}
}

ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *stream) __attribute__((alias("__getdelim")));

ssize_t getline(char **buf, size_t *bufsiz, FILE *stream) {
TRACE("intercepting getline(buf=%p, bufsiz=%p, stream=%p)\n", buf, bufsiz, stream)

Expand Down
58 changes: 58 additions & 0 deletions src/c/tests/test_getline_getdelim.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2019 CEA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#define _GNU_SOURCE
#include <unistd.h>
#include <assert.h>
#include "tests.h"

int test_getline_getdelim() {

int n = 0;

FILE* f = fopen(TESTFILE, "w");
CHECK_NULL(f, "fopen")

n = fprintf(f, "Hello World !\n");
CHECK_ERROR(n, "fprintf")
n = fprintf(f, "Hello Go !\n");
CHECK_ERROR(n, "fprintf")

fclose(f);

f = fopen(TESTFILE, "r");
CHECK_NULL(f, "fopen")

char * line = NULL;
size_t len = 0;
ssize_t read = 0;

read = getline(&line, &len, f);
CHECK_ERROR(read, "getline")

assert(strncmp(line, "Hello World !\n", 14) == 0);

read = getdelim(&line, &len, '\n', f);
CHECK_ERROR(read, "getdelim")

assert(strncmp(line, "Hello Go !\n", 11) == 0);

free(line);
fclose(f);
unlink(TESTFILE);

return 0;
}
6 changes: 6 additions & 0 deletions src/c/tests/testsuite.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
// from libc-testsuite

#include <stdio.h>
#include <unistd.h>
#include "tests.h"

#define RUN_TEST(a) { \
extern int test_ ##a (void); \
Expand All @@ -30,6 +32,9 @@ int main()
{
int err=0;

// clean pre-existing test file
unlink(TESTFILE);

RUN_TEST(access);
RUN_TEST(feof);
RUN_TEST(fgets);
Expand All @@ -38,6 +43,7 @@ int main()
RUN_TEST(fputc_fgetc);
RUN_TEST(ftruncate);
RUN_TEST(fwrite_fread);
RUN_TEST(getline_getdelim);
RUN_TEST(lseek);
RUN_TEST(mkdir_rmdir);
RUN_TEST(open_close);
Expand Down

0 comments on commit a970559

Please sign in to comment.