gothenburgbitfactory / libshared Goto Github PK
View Code? Open in Web Editor NEWLibshared - Common Code Submodule
License: Other
Libshared - Common Code Submodule
License: Other
The _COLOR_BRIGHT
flag should be separated into _COLOR_FGBRIGHT
and _COLOR_BGBRIGHT
to allow accessing the upper 8 colors in ANSI mode. Particularly this allows access to bright and bold colors.
The output coding currently as:
Line 487 in ba9b76d
result += colorstring[((_value & _COLOR_FGBRIGHT ? 89 : 29) + (_value & _COLOR_FG))];
Currently it's possible to trick the existing code into giving bright and bold colors by requesting inverse bright bold <background> on <foreground>
but this is really quite ugly.
It looks like the GitHub actions for this repo will not run with the current Taskwarrior, as it does not use the out-of-source build and ctest.
cc @felixschurk
Work week endings may be calculated incorrectly. Observe the following:
$ for ww in {s,e}o{,p,n}ww
do printf "%s\t%s\n" $ww $(
faketime '2017-03-05 12:34:56' task calc $ww
); done
soww 2017-03-13T00:00:00
sopww 2017-02-27T00:00:00
sonww 2017-03-13T00:00:00
eoww 2017-03-10T23:59:59
eopww 2017-03-03T23:59:59
eonww 2017-03-17T23:59:59
with the reference date of 2017-03-05 12:34:56 (a Sunday), and the calendar:
$ ncal 03 2017
March 2017
Mo 6 13 20 27
Tu 7 14 21 28
We 1 8 15 22 29
Th 2 9 16 23 30
Fr 3 10 17 24 31
Sa 4 11 18 25
Su 5 12 19 26
9 10 11 12 13
these do not look right:
soww
and sonww
are identicaleoww
is earlier than soww
(!)This issue was noticed during testing for #47 (a change to comments documenting behavior of eo*
) and is forked into a standalone issue as per the discussion there.
(test version of libshared
was 591fa58)
src/libshared/src/Datetime.cpp:3047]: (warning) Logical disjunction always evaluates to true: number >= 11 || number <= 13.
Source code is
if (((number >= 11 || number <= 13) && suffix == "th") ||
$ date
Wed Jul 7 22:18:59 2021
# ^^^ summer time
$ TZ="Europe/Dublin" ./run_all
Passed: 8283
Failed: 54
Unexpected successes: 0
Skipped: 1
Expected failures: 0
Runtime: 0.30 seconds
Seems like some actual values about an hour off:
$ make test
<...>
ok 3152 - eoq > now
actual (first - relative:true): 20210731T230000Z now: 20210707T211751Z
ok 3153 - 1st not in same month as now
ok 3154 - 1st day is 1
actual (second - relative:true): 20210801T230000Z now: 20210707T211751Z
ok 3155 - 2nd not in same month as now
ok 3156 - 2nd day is 2
actual (third - relative:true): 20210802T230000Z now: 20210707T211751Z
ok 3157 - 3rd not in same month as now
ok 3158 - 3rd day is 3
actual (fourth - relative:true): 20210803T230000Z now: 20210707T211751Z
ok 3159 - 4th not in same month as now
ok 3160 - 4th day is 4
actual (first - relative:false): 20210630T230000Z now: 20210707T211751Z
ok 3161 - 1st in same month as now
ok 3162 - 1st day is 1
actual (second - relative:false): 20210701T230000Z now: 20210707T211751Z
ok 3163 - 2nd in same month as now
ok 3164 - 2nd day is 2
actual (third - relative:false): 20210702T230000Z now: 20210707T211751Z
ok 3165 - 3rd in same month as now
ok 3166 - 3rd day is 3
actual (fourth - relative:false): 20210703T230000Z now: 20210707T211751Z
ok 3167 - 4th in same month as now
<...>
However:
$ TZ="UTC" ./run_all
Passed: 8337
Failed: 0
Unexpected successes: 0
Skipped: 1
Expected failures: 0
Runtime: 0.30 seconds
$ TZ="America/Los_Angeles" ./run_all
Passed: 8337
Failed: 0
Unexpected successes: 0
Skipped: 1
Expected failures: 0
Runtime: 0.30 seconds
I didn't dig any further.
char *foobar = "lorem ipsum";
format("dolor sit {1} amet", foobar);
Expected result:
"dolor sit lorem ipsum amet"
Actual result:
"dolor sit dolor sit amet amet"
When passing in a char*
-type variable to format
's varargs list, need to cast the variable to std::string
or convert it to a std::string
. Not doing so results in fmt
variable (first arg) being read a second time as one of the vararg variables.
Not a major issue but this small wart can take people by surprise - if this is wontfix, may I recommend adding a comment in the source?
The json::object::parse_pair
function calls getQuoted
to parse object keys. This means that object::_data
contains JSON-escaped keys.
This causes the following issue in timewarrior as of GothenburgBitFactory/timewarrior@bdb28fa:
$ timew start '"a'
Note: '"\"a"' is a new tag.
Tracking "\"a"
[…]
$ timew stop
Trying to decrement non-existent tag '"a'
After timew start
is run, the tags.data
file contains {"\"a":{"count":1}}
. When running timew stop
, libshared's parse_pair
parses the key "\"a"
, but does not unescape it. This causes timewarrior not to find "a
because the key is internally stored as \"a
.
Possible solutions:
_data
to store the unescaped stringPossibly related to GothenburgBitFactory/timewarrior#159
Whilst fuzzing with AFL I observed two unique crashes with similar input. Provided to task rc:$file list
. As the crash occurred inside libshared I'm reporting the problem here. Please let me know if I should file the bug in the taskwarrior repository instead.
This appears to be an infinite loop through Directory::create
which ends up exhausting the stack:
infinite_loop.rc:
data.location=/\
gdb-peda$ run rc:infinite_loop.rc list
Starting program: /home/kali/fuzzing/sessions/taskwarrior/task rc:infinite_loop.rc list
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Warning: AFL++ tools will need to set AFL_MAP_SIZE to 70464 to be able to run this instrumented program!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0xf9a3
RBX: 0x0
RCX: 0x7ebb00 --> 0x0
RDX: 0xcd
RSI: 0x7fffff7ff090 --> 0x7fffff7ff0a0 --> 0x0
RDI: 0x7fffff7ff048 --> 0x7fffff7ff058 --> 0x0
RBP: 0x7fffff7ff058 --> 0x0
RSP: 0x7fffff7fef90
RIP: 0x6ffb2c (<_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+60>: mov QWORD PTR [rsp+0x8],rbx)
R8 : 0x9ff050 --> 0x9fee10 --> 0x9fed50 --> 0xa03ad0 --> 0x9ff7d0 --> 0xa06cd0 (--> ...)
R9 : 0x3
R10: 0xfffffffffffff9dd
R11: 0x246
R12: 0x7fffff7ff0f0 --> 0x0
R13: 0x7fffff7ff090 --> 0x7fffff7ff0a0 --> 0x0
R14: 0x7fffff7ff048 --> 0x7fffff7ff058 --> 0x0
R15: 0x7fffff7ff0a0 --> 0x0
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x6ffb22 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+50>: mov QWORD PTR [rdi],rbp
0x6ffb25 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+53>: mov r15,QWORD PTR [rsi]
0x6ffb28 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+56>: mov rbx,QWORD PTR [rsi+0x8]
=> 0x6ffb2c <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+60>: mov QWORD PTR [rsp+0x8],rbx
0x6ffb31 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+65>: cmp rbx,0xf
0x6ffb35 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+69>: jbe 0x6ffb93 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+163>
0x6ffb37 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+71>: movsxd rax,DWORD PTR [rip+0xe42ba] # 0x7e3df8
0x6ffb3e <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+78>: mov rcx,QWORD PTR [rip+0xa5c03] # 0x7a5748 <__afl_area_ptr>
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x7fffff7fef90
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0x7fffff7ff048, Python Exception <class 'gdb.error'> There is no member named _M_dataplus.:
__str=) at /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h:451
451 { _M_construct(__str._M_data(), __str._M_data() + __str.length()); }
gdb-peda$
This file seems to trigger a crash inside Path::expand
:
path_expand_segv.rc:
data.location=/o
gdb-peda$ run rc:path_expand_segv.rc list
Starting program: /home/kali/fuzzing/sessions/taskwarrior/task rc:path_expand_segv.rc list
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Warning: AFL++ tools will need to set AFL_MAP_SIZE to 70464 to be able to run this instrumented program!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0xf993
RBX: 0x7fffff7ff0b0 --> 0x7fffff7ff0c0 --> 0x7fffff7ff100 --> 0x1
RCX: 0x7ebb00 --> 0x0
RDX: 0xf
RSI: 0x7fffff7ff080 --> 0x7fffff7ff090 --> 0x0
RDI: 0x7fffff7ff038 --> 0x0
RBP: 0x0
RSP: 0x7fffff7ff000 --> 0x7fffff7ff0e0 --> 0x0
RIP: 0x6ffaf9 (<_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+9>: push rbx)
R8 : 0x9ff050 --> 0x9fee10 --> 0x9fed50 --> 0xa03ad0 --> 0x9ff7d0 --> 0xa06cd0 (--> ...)
R9 : 0x2
R10: 0xfffffffffffff9dd
R11: 0x246
R12: 0x7fffff7ff0e0 --> 0x0
R13: 0x9ec001 --> 0x9100000000000000
R14: 0x7fffff7ff080 --> 0x7fffff7ff090 --> 0x0
R15: 0x7fffff7ff0c0 --> 0x7fffff7ff100 --> 0x1
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x6ffaf3 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+3>: push r14
0x6ffaf5 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+5>: push r13
0x6ffaf7 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+7>: push r12
=> 0x6ffaf9 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+9>: push rbx
0x6ffafa <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+10>: sub rsp,0x78
0x6ffafe <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+14>: movsxd rax,DWORD PTR [rip+0xe42eb] # 0x7e3df0
0x6ffb05 <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+21>: mov rcx,QWORD PTR [rip+0xa5c3c] # 0x7a5748 <__afl_area_ptr>
0x6ffb0c <_ZN4Path6expandERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+28>: mov dl,BYTE PTR [rcx+rax*1]
[------------------------------------stack-------------------------------------]
0000| 0x7fffff7ff000 --> 0x7fffff7ff0e0 --> 0x0
0008| 0x7fffff7ff008 --> 0x9ec001 --> 0x9100000000000000
0016| 0x7fffff7ff010 --> 0x7fffff7ff080 --> 0x7fffff7ff090 --> 0x0
0024| 0x7fffff7ff018 --> 0x7fffff7ff0c0 --> 0x7fffff7ff100 --> 0x1
0032| 0x7fffff7ff020 --> 0x0
0040| 0x7fffff7ff028 --> 0x6ff894 (<_ZN4PathC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+100>: mov rsi,QWORD PTR [rsp+0x8])
0048| 0x7fffff7ff030 --> 0x0
0056| 0x7fffff7ff038 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000000006ffaf9 in Path::expand (Python Exception <class 'gdb.error'> There is no member named _M_dataplus.:
in=) at /home/kali/fuzzing/victims/taskwarrior/src/libshared/src/FS.cpp:265
265 {
gdb-peda$
Either integrate std::regex or abandon RX in favor of std::regex.
The Color class should support true color, 8 bits per channel.
Thomas suggestion.
This is somehow related to #23 and GothenburgBitFactory/timewarrior#309.
I noticed that when setting the width
parameter of wrapText(...)
to 1
it fails (hangs indefinetly) when hyphenation is turned on:
text = "one";
lines.clear ();
wrapText (lines, text, 1, true);
Without hyphenation, it passes:
text = "one";
lines.clear ();
wrapText (lines, text, 1, false);
t.is (lines.size (), (size_t) 3, "wrapText 'one' -> 3 lines");
t.is (lines[0], "o", "wrapText line 0 -> 'o'");
t.is (lines[1], "n", "wrapText line 1 -> 'n'");
t.is (lines[2], "e", "wrapText line 1 -> 'e'");
Currently only durations longer than a year are allowed to be more precise than integers. It would be nice if shorter durations are also more precise or are allowed to receive a precision parameter.
https://github.com/GothenburgBitFactory/libshared/blob/master/src/Duration.cpp#L494
The following lines will cause Timewarrior 1.3.0 to hang indefinetely (GothenburgBitFactory/timewarrior#309):
$ src/timew track 2016-01-16T08:55:00 - 2016-01-16T09:00:00 "안녕하세요 월드"
Note: '"안녕하세요 월드"' is a new tag.
Recorded "안녕하세요 월드"
Started 2016-01-16T08:55:00
Ended 09:00:00
Total 0:05:00
$ src/timew day 2016-01-16 - 2016-01-17
I can reproduce this by adding the following test to shared.t.cpp:65
:
text = "안녕하세요 월드";
lines.clear ();
wrapText (lines, text, 1, false);
This test passes if the width
parameter in wrapText(...)
gets set to 2
:
text = "안녕하세요 월드";
lines.clear ();
wrapText (lines, text, 2, false);
t.is (lines.size (), (size_t) 7, "wrapText '안녕하세요 월드' -> 8 lines");
t.is (lines[0], "안", "wrapText line 0 -> '안'");
t.is (lines[1], "녕", "wrapText line 1 -> '녕'");
t.is (lines[2], "하", "wrapText line 2 -> '하'");
t.is (lines[3], "세", "wrapText line 3 -> '세'");
t.is (lines[4], "요", "wrapText line 4 -> '요'");
//t.is (lines[5], " ", "wrapText line 5 -> ' '");
t.is (lines[5], "월", "wrapText line 6 -> '월'");
t.is (lines[6], "드", "wrapText line 7 -> '드'");
However, the whitespace in 안녕하세요 월드
gets omitted somehow, so there is not empty line 5
Adding +#define _DEFAULT_SOURCE
at
Line 27 in 9a5f24e
-DCMAKE_CXX_FLAGS="-D_STANDARD_SOURCE"
when building taskwarrior doesn't seem to pass it over to libsharedImplements the changes of GothenburgBitFactory/timewarrior#407
Path::is_readable (and similar) fail when a symlink is broken.
The File class should be able to read compressed or uncompressed content via zlib, and present the same interface.
when writing tests for something else I discovered this:
$ date
Fri Jul 16 21:30:41 PDT 2021
$ task calc soy
2021-01-01T00:00:00
$ task calc sod
2021-07-16T00:00:00
$ task calc som
2021-07-01T00:00:00
(same in 2.5.3 and 2.6.0 trunk) but all the documentation says that soX
should be start of the next X
. Is this known behavior that has changed somewhere, or am I misunderstanding the description from man page:
Start of next (work) week (Monday), calendar week (Sunday or
Monday), month, quarter and year
task ... due:sow
task ... due:soww
task ... due:socw
task ... due:som
task ... due:soq
task ... due:soy
this seems confusing, there is "start of next ..." and "end of current" documented, but nothing for "start of current" which seems to be the actual behavior (not "next"). The tests in libshared/test/datetime.t.cpp
seem to agree with the behavior:
Datetime r19a ("soy");
t.ok (r19a.sameYear (now), "soy in same year as now");
t.ok (r19a < now, "soy < now");
but my understanding of the phrase "start of next " means that by definition, it's in the future. What am I missing?
Hello,
Path::expand() doesn't expand .foo
, the return value is .foo
and it should be /cwd/.foo
.
When tilde ~ appears in the middle of the path, it's also expanded as the user's home dir.
I am not sure if it was designed to be able to expand paths like .
and ./
because these two paths are not expanded too.
Thank you.
There seems to be an issue in this library regarding week numbers and starting day of week.
ISO weeks start on Monday. The code seems to agree:
src/Datetime.cpp:62:int Datetime::weekstart = 1; // Monday, per ISO-8601.
In the tests from test/datetime.t.cpp
there are some initialized variables:
...
int year = 2013;
int mo = 12;
...
local_now->tm_year = year - 1900;
local_now->tm_mon = mo - 1;
local_now->tm_mday = 1;
local_now->tm_isdst = 0;
time_t local1 = mktime (local_now);
std::cout << "# local midnight 2013-12-01 " << local1 << '\n';
We can see the local1
date is december 1:
$ grep local.midnight.2013-12-01 test/all.log
# local midnight 2013-12-01 1385884800
$ date -d @1385884800
Sun Dec 1 00:00:00 PST 2013
Now the following test is performed:
testParse (t, "2013-W49", 8, year, 0, 49, 0, 0, 0, 0, 0, false, local1);
...
Breakpoint 2, testParse (t=..., input="2013-W49", in_start=8,
in_year=2013, in_month=0, in_week=49, in_weekday=0, in_julian=0,
in_day=0, in_seconds=0, in_offset=0, in_utc=false,
in_date=1385884800)
at /home/scott/upsrc/libshared/test/datetime.t.cpp:47
47 {
(gdb) n
48 std::string label = std::string ("Datetime::parse (\"") +
input + "\") --> ";
(gdb)
50 Datetime iso;
(gdb)
51 std::string::size_type start = 0;
(gdb)
53 t.ok (iso.parse (input, start), label + "true");
(gdb)
ok 147 - Datetime::parse ("2013-W49") --> true
54 t.is ((int) start, in_start, label + "[]");
(gdb) p iso
$1 = {static weekstart = 1, static standaloneDateEnabled = true,
static standaloneTimeEnabled = true, static timeRelative = true,
_year = 2013, _month = 0, _week = 49, _weekday = 0, _julian = 0,
_day = 0, _seconds = 0, _offset = 0, _utc = false,
_date = 1385884800}
(gdb) n
ok 148 - Datetime::parse ("2013-W49") --> []
55 t.is (iso._year, in_year, label + "_year");
(gdb) n
ok 149 - Datetime::parse ("2013-W49") --> _year
56 t.is (iso._month, in_month, label + "_month");
(gdb)
ok 150 - Datetime::parse ("2013-W49") --> _month
57 t.is (iso._week, in_week, label + "_week");
(gdb)
ok 151 - Datetime::parse ("2013-W49") --> _week
So the test's expectation is that 2013 week 49 is December 1:
$ task calc 2013-W49
2013-12-01T00:00:00
Yet, it isn't:
$ ncal 12 2013
December 2013
Mo 2 9 16 23 30
Tu 3 10 17 24 31
We 4 11 18 25
Th 5 12 19 26
Fr 6 13 20 27
Sa 7 14 21 28
Su 1 8 15 22 29
48 49 50 51 52 1
$ date -d `task calc 2013-W49` +%V
48
The week number is wrong, December 1 is still week 48, not week 49. The problem seems to be that it's treating Sunday as the first day of week 49.
Timewarrior does not set or pass weekstart
to libshared anywhere, so presumably the libshared default is always used (weekstart = 1
, Monday, ISO weeks, as initialized above in Datetime.cpp:62).
Taskwarrior does have an rc.weekstart
, but it makes no difference:
$ for ws in 0 1 Sunday Monday
do task rc.weekstart=$ws calc 2013-W49
done
2013-12-01T00:00:00
2013-12-01T00:00:00
2013-12-01T00:00:00
2013-12-01T00:00:00
This is leading to problems such as in GothenburgBitFactory/timewarrior#595 and GothenburgBitFactory/taskwarrior#2922 with no obvious fix.
I will keep digging into this as time permits. If anyone else knows anything more about this, it would be helpful.
I thought about making this project a standalone lib.
This happened after I saw both Task Warrior and Timewarrior use the same library and that I am building it twice.
And googled this name and I found another project of the same name (born at the similar time, Jul 16, 2016):
https://github.com/soymuchacho/libshared
Would it be acceptable for this project to adjust the name? Just a thought.
In support of GothenburgBitFactory/taskwarrior#3333 -- older Taskwarrior's create JSON by just blasting bytes into a file, and if that contains invalid utf-8 then the import process will not work.
@lauft I see you've made other changes in this repo. Is this something you could work on, by any chance?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.