Skip to content

Commit 110d477

Browse files
committed
Squashed 'libreadtags/' changes from 203af8750..3f5fba867
3f5fba867 Merge pull request #42 from masatake/revise-test-case a05721ba2 tests: report failure if TagErrnoFileMaybeTooBig is set 6c2c21a52 Merge pull request #40 from masatake/masatake--lambertlulala-fix/limitation_of_ftell_and_fseek a222fcf22 pass 0 instead of 0L to fseek() as the beginning of a file stream 4c2f6b2bc update NEWS.md 195173214 Add _WIN32 preprocessor to use _ftelli64 and _fseeki64 167834bd2 Merge pull request #39 from masatake/add-error-const-for-too-large-tags 096152e47 style: delete a redundant usage of 'else' keyword 6dca8a888 Introduce a new error constant TagErrnoFileMaybeTooBig 31e93940d GitHub Actions: show the test log in failure 0f6a0c281 cosmetic: clean up whitespaces 4a6bca8f6 Merge pull request #38 from universal-ctags/masatake-patch-1 e2a4a43c2 GitHub Actions: run test cases on msys2 and mingw 32f4a95eb Merge pull request #35 from masatake/fix-comment c5182322f comments: fix a typo git-subtree-dir: libreadtags git-subtree-split: 3f5fba867cc2c6a5654ab8c80775c060fa93b633
1 parent 557bfce commit 110d477

File tree

8 files changed

+317
-45
lines changed

8 files changed

+317
-45
lines changed

.github/workflows/msys2.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#
2+
# Derrived from .github/workflows/testing-msys2.yml of universal-ctags/ctags repo
3+
#
4+
name: run test cases on MSYS2
5+
6+
on:
7+
push:
8+
branches: [ master ]
9+
pull_request:
10+
branches: [ master ]
11+
12+
jobs:
13+
testing:
14+
runs-on: windows-latest
15+
16+
strategy:
17+
matrix:
18+
msystem: [MSYS, MINGW32, MINGW64]
19+
20+
defaults:
21+
run:
22+
shell: msys2 {0}
23+
24+
steps:
25+
- uses: msys2/setup-msys2@v2
26+
with:
27+
msystem: ${{ matrix.msystem }}
28+
update: true
29+
install: git make automake1.16 autoconf libtool
30+
31+
- if: matrix.msystem == 'MSYS'
32+
run: pacman -S --noconfirm gcc
33+
34+
- if: matrix.msystem == 'MINGW32'
35+
run: pacman -S --noconfirm mingw-w64-i686-toolchain
36+
37+
- if: matrix.msystem == 'MINGW64'
38+
run: pacman -S --noconfirm mingw-w64-x86_64-toolchain
39+
40+
- run: ln -s /usr/bin/automake-1.16 /usr/bin/automake
41+
- run: ln -s /usr/bin/aclocal-1.16 /usr/bin/aclocal
42+
43+
- run: git config --global core.autocrlf input
44+
shell: bash
45+
- uses: actions/checkout@v2
46+
47+
- run: ./autogen.sh
48+
- run: ./configure --prefix=/usr
49+
- run: make V=1
50+
- run: make check V=1
51+
- run: cat tests/test-suite.log
52+
if: failure()

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@ tests/test-api-tagsFirst
3737
tests/test-api-tagsFirstPseudoTag
3838
tests/test-api-tagsOpen
3939
tests/test-api-tagsSetSortType
40+
tests/test-fix-large-tags
4041
tests/test-fix-null-deref
4142
tests/test-fix-unescaping

NEWS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
- fix potential crashes trigged when passing NULL as `file` parameter
77
to the API functions. Provided by rootkea (GitHub account).
88

9+
- add a new error constant `TagErrnoFileMaybeTooBig` to represent
10+
the case that the given tags file is too large for the platform APIs
11+
(ftell and fseek) used in libreadtags.
12+
See https://github.com/universal-ctags/libreadtags/issues/36 about the
13+
background of this change.
14+
15+
- allow the library to read larger (> 2G) tag files on Win32 platform.
16+
The tag file size was limited to 2G on the platform because the library
17+
used fseek and ftell. In this version, they are replaced with _fseeki64 and
18+
_ftelli64.
19+
920
# Version 0.1.0
1021

1122
- propagate internal errors to caller

configure.ac

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ AC_PROG_LIBTOOL
2424
# 1:0:0
2525
# introduced tagsGetErrno() and tagErrno.
2626
# rename sortType to tagSortType.
27-
28-
AC_SUBST(LT_VERSION, [1:0:0])
27+
#
28+
# 2:0:1
29+
# introduced TagErrnoFileMayTooBig.
30+
#
31+
AC_SUBST(LT_VERSION, [2:0:1])
2932

3033
AC_ARG_ENABLE([gcov],
3134
[AS_HELP_STRING([--enable-gcov],

readtags.c

Lines changed: 85 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ typedef struct {
3232
char *buffer;
3333
} vstring;
3434

35+
/* Define readtags' own off_t. */
36+
#ifdef _WIN32
37+
typedef long long rt_off_t;
38+
#else
39+
typedef off_t rt_off_t;
40+
#endif
41+
3542
/* Information about current tag file */
3643
struct sTagFile {
3744
/* has the file been opened and this structure initialized? */
@@ -43,17 +50,17 @@ struct sTagFile {
4350
/* pointer to file structure */
4451
FILE* fp;
4552
/* file position of first character of `line' */
46-
off_t pos;
53+
rt_off_t pos;
4754
/* size of tag file in seekable positions */
48-
off_t size;
55+
rt_off_t size;
4956
/* last line read */
5057
vstring line;
5158
/* name of tag in last line read */
5259
vstring name;
5360
/* defines tag search state */
5461
struct {
5562
/* file position of last match for tag */
56-
off_t pos;
63+
rt_off_t pos;
5764
/* name of tag last searched for */
5865
char *name;
5966
/* length of name for partial matches */
@@ -97,6 +104,32 @@ static const size_t PseudoTagPrefixLength = 2;
97104
* FUNCTION DEFINITIONS
98105
*/
99106

107+
static rt_off_t readtags_ftell(FILE *fp)
108+
{
109+
rt_off_t pos;
110+
111+
#ifdef _WIN32
112+
pos = _ftelli64(fp);
113+
#else
114+
pos = ftell(fp);
115+
#endif
116+
117+
return pos;
118+
}
119+
120+
static int readtags_fseek(FILE *fp, rt_off_t pos, int whence)
121+
{
122+
int ret;
123+
124+
#ifdef _WIN32
125+
ret = _fseeki64(fp, pos, whence);
126+
#else
127+
ret = fseek(fp, pos, whence);
128+
#endif
129+
130+
return ret;
131+
}
132+
100133
/* Converts a hexadecimal digit to its value */
101134
static int xdigitValue (char digit)
102135
{
@@ -285,7 +318,7 @@ static int readTagLineRaw (tagFile *const file, int *err)
285318
char *const pLastChar = file->line.buffer + file->line.size - 2;
286319
char *line;
287320

288-
file->pos = ftell (file->fp);
321+
file->pos = readtags_ftell (file->fp);
289322
if (file->pos < 0)
290323
{
291324
*err = errno;
@@ -312,7 +345,8 @@ static int readTagLineRaw (tagFile *const file, int *err)
312345
*err = ENOMEM;
313346
result = 0;
314347
}
315-
if (fseek (file->fp, file->pos, SEEK_SET) < 0)
348+
349+
if (readtags_fseek (file->fp, file->pos, SEEK_SET) < 0)
316350
{
317351
*err = errno;
318352
result = 0;
@@ -748,7 +782,7 @@ static tagResult gotoFirstLogicalTag (tagFile *const file)
748782
{
749783
fpos_t startOfLine;
750784

751-
if (fseek(file->fp, 0L, SEEK_SET) == -1)
785+
if (readtags_fseek(file->fp, 0, SEEK_SET) == -1)
752786
{
753787
file->err = errno;
754788
return TagFailure;
@@ -804,31 +838,40 @@ static tagFile *initialize (const char *const filePath, tagFileInfo *const info)
804838
info->status.error_number = errno;
805839
goto file_error;
806840
}
807-
else
808-
{
809-
if (fseek (result->fp, 0, SEEK_END) == -1)
810-
{
811-
info->status.error_number = errno;
812-
goto file_error;
813-
}
814-
result->size = ftell (result->fp);
815-
if (result->size == -1)
816-
{
817-
info->status.error_number = errno;
818-
goto file_error;
819-
}
820-
if (fseek(result->fp, 0L, SEEK_SET) == -1)
821-
{
822-
info->status.error_number = errno;
823-
goto file_error;
824-
}
825841

826-
if (readPseudoTags (result, info) == TagFailure)
827-
goto file_error;
842+
/* Record the size of the tags file to `size` field of result. */
843+
if (readtags_fseek (result->fp, 0, SEEK_END) == -1)
844+
{
845+
info->status.error_number = errno;
846+
goto file_error;
847+
}
848+
result->size = readtags_ftell (result->fp);
849+
if (result->size == -1)
850+
{
851+
/* fseek() retruns an int value.
852+
* We observed following behavior on Windows;
853+
* if sizeof(int) of the platform is too small for
854+
* representing the size of the tags file, fseek()
855+
* returns -1 and it doesn't set errno.
856+
*/
857+
info->status.error_number = errno;
858+
if (info->status.error_number == 0)
859+
info->status.error_number = TagErrnoFileMaybeTooBig;
828860

829-
info->status.opened = 1;
830-
result->initialized = 1;
861+
goto file_error;
831862
}
863+
if (readtags_fseek(result->fp, 0, SEEK_SET) == -1)
864+
{
865+
info->status.error_number = errno;
866+
goto file_error;
867+
}
868+
869+
if (readPseudoTags (result, info) == TagFailure)
870+
goto file_error;
871+
872+
info->status.opened = 1;
873+
result->initialized = 1;
874+
832875
return result;
833876
mem_error:
834877
info->status.error_number = ENOMEM;
@@ -905,9 +948,9 @@ static const char *readFieldValue (
905948
return result;
906949
}
907950

908-
static int readTagLineSeek (tagFile *const file, const off_t pos)
951+
static int readTagLineSeek (tagFile *const file, const rt_off_t pos)
909952
{
910-
if (fseek (file->fp, pos, SEEK_SET) < 0)
953+
if (readtags_fseek (file->fp, pos, SEEK_SET) < 0)
911954
{
912955
file->err = errno;
913956
return 0;
@@ -951,11 +994,11 @@ static tagResult findFirstNonMatchBefore (tagFile *const file)
951994
#define JUMP_BACK 512
952995
int more_lines;
953996
int comp;
954-
off_t start = file->pos;
955-
off_t pos = start;
997+
rt_off_t start = file->pos;
998+
rt_off_t pos = start;
956999
do
9571000
{
958-
if (pos < (off_t) JUMP_BACK)
1001+
if (pos < (rt_off_t) JUMP_BACK)
9591002
pos = 0;
9601003
else
9611004
pos = pos - JUMP_BACK;
@@ -971,7 +1014,7 @@ static tagResult findFirstMatchBefore (tagFile *const file)
9711014
{
9721015
tagResult result = TagFailure;
9731016
int more_lines;
974-
off_t start = file->pos;
1017+
rt_off_t start = file->pos;
9751018
if (findFirstNonMatchBefore (file) != TagSuccess)
9761019
return TagFailure;
9771020
do
@@ -988,10 +1031,10 @@ static tagResult findFirstMatchBefore (tagFile *const file)
9881031
static tagResult findBinary (tagFile *const file)
9891032
{
9901033
tagResult result = TagFailure;
991-
off_t lower_limit = 0;
992-
off_t upper_limit = file->size;
993-
off_t last_pos = 0;
994-
off_t pos = upper_limit / 2;
1034+
rt_off_t lower_limit = 0;
1035+
rt_off_t upper_limit = file->size;
1036+
rt_off_t last_pos = 0;
1037+
rt_off_t pos = upper_limit / 2;
9951038
while (result != TagSuccess)
9961039
{
9971040
if (! readTagLineSeek (file, pos))
@@ -1083,18 +1126,18 @@ static tagResult find (tagFile *const file, tagEntry *const entry,
10831126
file->search.nameLength = strlen (name);
10841127
file->search.partial = (options & TAG_PARTIALMATCH) != 0;
10851128
file->search.ignorecase = (options & TAG_IGNORECASE) != 0;
1086-
if (fseek (file->fp, 0, SEEK_END) < 0)
1129+
if (readtags_fseek (file->fp, 0, SEEK_END) < 0)
10871130
{
10881131
file->err = errno;
10891132
return TagFailure;
10901133
}
1091-
file->size = ftell (file->fp);
1134+
file->size = readtags_ftell (file->fp);
10921135
if (file->size == -1)
10931136
{
10941137
file->err = errno;
10951138
return TagFailure;
10961139
}
1097-
if (fseek(file->fp, 0L, SEEK_SET) == -1)
1140+
if (readtags_fseek(file->fp, 0, SEEK_SET) == -1)
10981141
{
10991142
file->err = errno;
11001143
return TagFailure;
@@ -1167,7 +1210,7 @@ static tagResult findPseudoTag (tagFile *const file, int rewindBeforeFinding, ta
11671210

11681211
if (rewindBeforeFinding)
11691212
{
1170-
if (fseek(file->fp, 0L, SEEK_SET) == -1)
1213+
if (readtags_fseek(file->fp, 0, SEEK_SET) == -1)
11711214
{
11721215
file->err = errno;
11731216
return TagFailure;

readtags.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef enum {
5959
* (Zero or a positive integer is expected.) */
6060
TagErrnoInvalidArgument = -4, /* Unexpected argument passed to the API
6161
* function */
62+
TagErrnoFileMaybeTooBig = -5, /* Maybe the tags file is too big */
6263
} tagErrno;
6364

6465
struct sTagFile;
@@ -258,7 +259,7 @@ extern tagResult tagsFindNext (tagFile *const file, tagEntry *const entry);
258259

259260
/*
260261
* Does the same as tagsFirst(), but is specialized to pseudo tags.
261-
* If tagFileInfo doesn't contain pseudo tags you are interested, read
262+
* If tagFileInfo doesn't contain pseudo tags you are interested in, read
262263
* them sequentially with this function and tagsNextPseudoTag().
263264
*/
264265
extern tagResult tagsFirstPseudoTag (tagFile *const file, tagEntry *const entry);

tests/Makefile.am

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ TESTS = \
99
\
1010
test-fix-unescaping \
1111
test-fix-null-deref \
12+
test-fix-large-tags \
1213
\
1314
$(NULL)
1415

@@ -23,6 +24,7 @@ check_PROGRAMS = \
2324
\
2425
test-fix-unescaping \
2526
test-fix-null-deref \
27+
test-fix-large-tags \
2628
\
2729
$(NULL)
2830

@@ -80,3 +82,6 @@ EXTRA_DIST += unescaping.tags
8082
test_fix_null_deref = test-fix-null-deref.c
8183
test_fix_null_deref_DEPENDENCIES = $(DEPS)
8284
EXTRA_DIST += null-deref.tags
85+
86+
test_fix_large_tags = test-fix-large-tags.c
87+
test_fix_large_tags_DEPENDENCIES = $(DEPS)

0 commit comments

Comments
 (0)