gavinhoward / bc

An implementation of the POSIX bc calculator with GNU extensions and dc, moved away from GitHub. Finished, but well-maintained.
https://git.gavinhoward.com/gavin/bc
Other
145 stars 29 forks source link

dc bug when reading commands from stdin #31

Closed Math2 closed 4 years ago

Math2 commented 4 years ago
$ { echo 0; seq 1000 | sed -e 's;$;+;'; echo p; } > f
$ dc < f
146524
$ cat f | dc
146524
$ dc f
500500
gavinhoward commented 4 years ago

I have reproduced the bug. I am about to do a release, so I will include the fix, once I figure it out, in the release (3.0.4). Thank you for reporting it. Also, thank you for using my dc.

Math2 commented 4 years ago

Alright great! Thanks for your work. Hope the update makes it in FreeBSD-CURRENT.

Also, I just noticed another thing, but dunno if that would be worth trying to fix.

Say you give it an infinite input stream like this:

{ echo 0; jot 0 | sed -e 's;$;+;'; echo p; } | dc

Memory usage seems to build up infinitely. Whereas GNU and OpenBSD dc seem to be able to work with stable memory usage.

I noticed because I had that alias since forever and sometimes I use it to sum up a big input stream.

sum() { { echo '0'; sed -nE -e 's;([0-9]+);\1+;gp' "$@"; echo 'p'; } | dc; }

Memory usage seems to build up slow enough that it would have to be very very large before it starts being a problem but still.

gavinhoward commented 4 years ago

I believe I know what is causing the memory growth. I have a clean-up function, but it's quite conservative, and after thinking about it, I could probably make it more strict. I will do that as well.

gavinhoward commented 4 years ago

I have found and fixed both issues.

For the memory growth, it was exactly as I suspected: my clean-up routine was too conservative. I also needed to make sure to call it on every iteration of the input loop.

For the bug, it was because of a mishandling of strings, specifically not using a null character where I should have. See https://github.com/gavinhoward/bc/commit/5aecad927c732aeb91538c7af5ef50cc855ee0e8.

Please pull down the changes and test for yourself; I am going to run the tests on FreeBSD as well, but I want to make sure I actually solved your problem.

Math2 commented 4 years ago

Yup, everything seems to work well now. I made it sum a billion numbers from stdin (10GB input to process) and I'm letting it run with infinite input. Correct output and no crash and memory usage seems to remain stable forever.

Thanks for the quick fixing!

gavinhoward commented 4 years ago

You're welcome. I should have 3.0.4 out in a few days, and the maintainer of the FreeBSD import into base is aware of the coming release, so it should arrive soon after I release it.