| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
| |
* stdlib/path-test.tl (safe-abs-path): If (uname) doesn't
report Linux, then define this function in a way that it
always returns true. We do this by making the name an alias
for the tf function.
|
|
|
|
|
|
| |
* stdlib/path-test.tl (path-components-safe): Reject symlinks
that have a link count not equal to one. This looks
suspiciously like a hard link attack.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Attacks are possible via /proc/<pid>/fd/<n> involving
a deleted file, whereby the link target changes from
"/path/to/file" to "/path/to/file (deleted)", which
can be perpetrated by a different user, not related
to process <pid>, who has access to perform
unlink("/path/to/file").
* stdlib/path-test.tl (safe-abs-path): Perform the
pattern check regardless of effective user ID.
* tests/018/path-safe.tl: Test cases adjusted.
|
|
|
|
|
| |
* stdlib/path-test (path-components-safe): Remove empty
components from split path.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In a Linux system, it's possible for an unprivileged
user to create a root symlink pointing to any directory,
simply by changing to that directory and running a setuid
executable like "su". That executable will get a process
whose /proc/<pid> directory is root owned, and contains
a symlink named cwd pointing to the current directory.
Other symlinks under /proc look exploitable in this way.
* stdlib/path-test.tl (safe-abs-path): New function.
Here is where we are going to check for unsafe paths.
We use some pattern matching to recognize various unsafe
symlinks under /proc.
(path-components-safe): Simplify code around recognition
of absolute paths. When an absolute path is read from
a symlink, remove the first empty component. Pass every
absolute path through safe-abs-path to check for known
unsafe paths.
* tests/018/path-safe.tl: New tests.
|
|
|
|
|
|
|
|
| |
* stdlib/copy-file.tl (path-simplify, path-split, path-volume,
rel-path, path-equal): Remove from here.
* stdlib/path-test.tl: (path-simplify, path-split, path-volume,
rel-path, path-equal): Move to here.
|
|
|
|
|
|
| |
* lib.c (stringp): Examine tag and then type separately,
rather than using the canned type function. This leads to
slightly nicer code, shorter by a couple of instructions.
|
|
|
|
|
|
|
|
|
|
|
| |
* arith.c (gcd): New implementation which uses arithmetic
in the unsigned type ucnum if both operands are in that
type's range. This uses Stein's algorithm a.k.a.
binary GCD. The mpi_gcd function is used only if at least
one argument is a bignum whose value doesn't fit into
a ucnum.
* tests/016/arith.tl: gcd test cases added.
|
|
|
|
|
|
|
|
| |
* stdlib/socket.tl (in6addr-str): Remove one of
the two repetitions of a string substitution
intended to be done once. The substitution is
idempotent and therefore a second application
of it is redundant regardless of intent.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* txr.c (sysroot_init): Use regsub to look for "\\"
substring instead of regex.
* stdlib/getopts.tl (opt-parsed convert-type):
regsub for "0x" substring rather than #/0x/ regex.
* stdlib/pic.tl (pic-join-oipt): regsub for
"~" substring rather than #/\~/ regex.
* stdlib/socket.tl (in6addr-str): regsub for "::"
substring instead of #/::/ regex in two places.
The double regsub there looks like a mistake; will
address in another commit.
|
|
|
|
|
|
| |
* regex.c (regsub): Use search_str if regex is a string.
* txr.1: Documented.
|
|
|
|
|
|
| |
* regex.c (regsub): Accumulate output string directly
using string_extend, rather than accumulating a list
of pieces which are catenated with cat_str.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Summary: we now check the entire path of .txr_history and .txr_profile
files for security issues; we enforce that these files must not be
readable to other users, not just not writable. And there is a bugfix:
we do not load the history if it has a permission problem, instead of
loading it anyway and just issuing a diagnostic.
* repl.c (report_security_problem): Rename to report_file_perm_problem.
Drop the umask check, because we are going to be checking for files
that are not readable for others, which would require a stricter umask
than the usual 022.
(report_path_perm_problem): New static function.
(load_rcfile): Take the needed function symbols as arguments, because
the only caller is repl and it has them; it can pass them down.
Check the path using path-components-safe function, and bail with
an error message if it is bad. Then check the file using
path-strictly-private-to-me-p, rather than path-private-to-me-p
as previously. This requires the file not to be readable to others too.
(repl): path_private_to_me_p variable renamed to ppriv_s for brevity
and holds a different symbol: path-strictly-private-to-me-p,
the function which checks that other users cannot read the file, not
just write. Also capture the path-components-safe symbol as
psafe_s. ppriv_s and psafe_s are passed down to load_rcfile so it
can do checks. Like in the case of the rcfile, we now check the
history file using both functions, validating the path not just
the file's own permissions. Bugfix: we now check the history file's
path before loading the history file, and avoid loading it if the
check fails. We use the path-exists-p function now to check that
the history and rc files exist. That leaves a small flaw: an
attacker could be in control of the paths to these files and
manipulate these paths such that these files appear not to exist;
we will then not report on such a situation.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* stdlib/path-test.tl (path-components-safe): Simplify code;
forget trying to do anything on Windows: just return true.
* txr.1: Document that path-components-safe is useless
on Windows.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* autoload.c (path_test_set_entries): Autoload on
path-components-safe symbol.
* stdlib/path-test.tl (if-windows, if-native-windows):
New system macros.
(path-safe-sticky-dir): New system function.
(path-components-safe): New function.
* tests/018/path-safe.tl: New file.'
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
| |
* stdlib/path-test.tl (path-private-to-me,
path-strictly-private-to-me): Call (getuid) rather
than (geteuid). We won't revert this behavior with
the -C compat option because it's wrong/insecure.
* txr.1: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The compile-file function must only try a different
path, such as with a suffix, if a given path fails
to open due to non-existence. If the failure is for
another reason, like permissions. In that case we want
to propagate the failure.
* stdlib/compiler.tl (ign-notfound): New macro.
This lets through all errors, catching only path-not-found,
converting that to a nil result.
(open-compile-streams): Use ign-notfound instead of
ignerr when trying to open an input file for reading.
Also, we lose the ignerr wrapping around the open-file.
We let any error whatsoever just bubble out so that the user
is better informed about what went wrong. The requirement
to close the input stream is handled by the obvious
unwind-protect.
|
|
|
|
|
|
|
|
|
| |
* stdlib/compiler.tl (translate-hash-bang): New function.
(compile-file-conditionally): Use translate-hash-bang to
treat hash bang line.
* txr.1: Revised hash bang treatment by file compiler
documented.
|
|
|
|
|
|
|
|
| |
* stdlib/compiler.tl (open-compile-streams): If the in-path
is unsuffixed, try opening it without adding any suffix first.
If that fails, then try .tl in that order.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* txr.c (sysroot_init): The value of TXR_REL_PATH
already has the exe suffix on it if we are building
for Windows. There is no need to try with EXE_SUFF
tacked on to it. There is also no need to try PROG_NAME
with or without the suffix. EXE_SUFF is the empty
string on non-Windows platforms, so the two lines of
code are equivalent. On Windows, PROG_NAME without
the EXE_SUFF will not match; that maybe_sysroot call
is a waste of CPU cycles.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Makefile (LN): New variable. On platforms where
you can't hard link, this can be replaced with some
other command. Possibly "true" not to have the alternative
executable name created at all.
(HARDLINK): New macro.
(install): Use HARDLINK to create a link named txrlisp
pointing to the same file as txr in the destination
directory.
* txr.c (txr_main): If the executable ends with "lisp"
(or "lisp.exe" on Windows), then default the txr_lisp_p
variable to t, which has the effect as if --lisp had
been processed.
* txr.1: Documented.
|
|
|
|
| |
* txr.1: Improve unclear wording describing pos function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The general count function, with keyfun and testfun,
is noticeably absent. Let's implement it.
* lib.[ch] (count): New function.
* eval.c (eval_init): Register count intrinsic.
* tests/012/seq.tl: Some tests for count.
* txr.1: Add count to count-if section. Revise documentation
based on pos/pos-if.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
| |
* RELNOTES: 2022-07-01.
* txr.1: Likewise and two minor fixes.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* protsym.c: Regenerated.
|
|
|
|
|
|
|
|
|
| |
* txr.1: Remove references to limitations in open-process on
platforms which don't have fork. It's simply not implemented on
those platforms at all any more. This documentation referred
to a MinGW port of TXR which has not been maintained in many
years. Also remove text which says that open-subprocess is only
available on platforms with fork.
|
|
|
|
|
|
|
|
|
|
|
| |
* stdlib/getput.tl (command-get, command-put, command-get-string,
command-put-string, command-get-lines, command-put-lines,
command-put-buf, command-get-json, command-put-json,
command-get-jsons, command-put-jsons): Add mopt parameter,
which is interpolated into appropriate mode string.
This allows "z" to be used for gzip compression.
* txr.1: Updated Syntax synopses.
|
|
|
|
|
| |
* stdlib/getput.tl (file-get-lines): A mode-opt parameter is
documented for this function; it is now actually implemented.
|
|
|
|
|
|
|
|
|
| |
* stream.c (pipe_close_status_helper): Revise error messages.
Get rid of impossible cases: we will not get WIFSTOPPED or
WIFCONTINUED unless we used the WUNTRACED option in waitpid,
which we don't. No platforms without HAVE_SYS_WAIT, don't throw
if the status is nonzero; just return nil. It could be a normal
termination.
|
|
|
|
|
|
| |
* txr.1: pid argument is documented and also missing,
documentation added about how close-stream deals
with processes.
|
|
|
|
|
|
| |
* stream.c (pipe_close_status_helper, pipe_close, pipe_ops):
Included in #if HAVE_FORK_STUFF block.
(stream_init): Refer to pipe ops only if HAVE_FORK_STUFF is true.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is vestigial code from a time when TXR supported being
compiled with MinGW. Except in the case of the functions run
and sh, which are implementable without fork on Cygwin
using the spawn family of functions, there won't be any
fallback; if HAVE_FORK_STUFF is zero or missing, then certain
functions will be absent.
* stream.c (struct stdio_handle): Do not define a pid member
if we don't HAVE_FORK_STUFF.
(se_pclose): Function removed; we won't be using any
non-POSIX platforms popen/pclose.
(pipe_close): Don't call the removed se_pclose.
(make_pipe_stream): Function removed.
(fds_subst, fds_swizzle): Don't define these if
HAVE_FORK_STUFF is absent, and so is HAVE_WSPAWN and HAVE_SPAWN.
They are now only needed by the version of the run function
that uses spawn or wspawn.
(open_command, open_process): Remove the versions of these
function based on popen.
(string_extend_count, win_escape_cmd, win_escape_arg,
win_make_cmdline): Remove these functions used by the above
open_process; we have no need for encoding arguments into a
Windows command line string, since the Cygwin/Cygnal libraries
do that for us in their spawn and exec functions.
* stream.h (make_pipe_stream): Function removed.
* utf8.[ch] (w_popen): Function removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (pipe_close_status_helper): New function,
factored out of pipe_close and used by it, and
also by gzio_close.
(pipe_close): Call pipe_close, which now contains
the classification of process wait status codes.
(open_fileno): Now takes optional pid argument.
If this specified, then make_pipevp_stream is used.
(open_subprocess): Use the open_fileno function, rather than
fopen. This simplifies things too, except that we have to
catch exception. Pass pid to the newly added parameter of
open_fileno so that we obtain a proper pipe stream that will
wait for the process to terminate when closed.
(mkstemp_wrap): Pass nil for pid argument of open_fileno.
(stream_init): Update registration of open-fileno.
* gzio.c (struct gzio_handle): New member, pid.
(gzio_close): If there is a nonzero pid, wait for the
process to terminate.
(make_gzio_stream): Initialize h->pid to zero.
(make_gzio_pipe_stream): New function.
* parser.c (lino_fdopen): Pass nil for pid argument
of open_fileno.
* gzio.h (make_gzio_pipe_stream): Declared.
* tests/018/gzip.tl: New test.
|
|
|
|
| |
* configure (android_target): Remove unused variable.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* eval.c (me_for): Require at least one argument.
However, we let the init-forms continue to be optional
and document it.
* txr.1: Refer to for and for* as macros, since they have been
since 2016. The omission of the inc-form list is shown
as a second variant of the syntax. This is to avoid misleading
the reader into thinking that the the inc-form list can be
omitted while body forms are present. A spurious paragraph
reiterating that the macros establish an anonymous block is
removed. That extra text was present in the first draft written
in 2011, and maintained since.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The str function is like mkstring but allows a fill pattern
to be specified.
* eval.c (eval_init): str intrinsic registered.
* lib.[ch[ (str): New function.
* tests/015/str.tl: New file.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The following test case throws an exception:
(compile-toplevel '(when-match @(or
@b @c)
nil nil))
the reason is that in the optimizer, the local-liveness method
resets the bl.live set of live registers to nil. The expectation
is that it will be recalculated. However, what happens is that
* stdlib/optimize.tl (basic-block): Initialize live slot to zero.
(basic-blocks local-liveness): Reset bl.live to 0, rather than nil.
The problem is that sometimes the block in question is not reached
in the graph traversal (down in the same function) which is
supposed to assign it a live value. This happens in the above
test case, and it's not due to any bug: the block is not reached
by the forward traversal because the block has become unreachable.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The root slot is just supposed to be (car bl.list): the
first basic block. Unfortunately, it's not maintained
when bl.list is edited, which could cause bugs.
This change makes no difference in the stdlib compiled files,
other than of course the changes in optimize.tlo from this
code change itself; so that is evidence suggesting
this change is least not making anything worse.
* stdlib/optimize.tl (basic-blocks): Remove root slot.
(basic-blocks (link-graph, calc-liveness, elim-dead-code):
Refer to (car bl.list) instead of bl.root.
|
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (repl): Also push and pop the warning handler
around the linenoise call, like we do around evaluation.
The reason is that when the library is used in source code
form, it can generate warnings while loading. Loading can
be triggered by completion from inside linenoise. Neglecting
to handle warnings and throw a continue causes a problem
because the warnings then fall victim to the listener's
master catch. That then interferes with the load.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem being addressed here showed up for me when compiling with
either gcc-7 or gcc-11 on Ubuntu 18, using -fsanitize-undefined.
A few test test cases run under --gc-debug were crashing. I narrowed
it down to this small test case, whose correct output would be "1":
./txr --gc-debug -p '(sys:fmt-simple 1 : : : :)'
"\x6700ACB0缻\x6700ACB0缻 "
The issue doesn't have anything to do with -fsanitize-undefined;
that just how it got reproduced by chance. I'm reasonably certain
that in builds for which "make tests" passes, and the above test
case doesn't repro, this issue is absent: the code got generated
in such a way that it the string_own call doesn't cause the stream
object to be reclaimed.
* stream.c (get_string_from_stream): change the order of operations in
the ownership transfer of the string from the stream to the returned
string object. We capture the string in a local variable, and null out
so->buf before calling string_own. The problem is that
get_string_from_stream is called in a way where the caller no longer
has any use for the stream, and so the object is no longer live.
It's possible for the string_own call to cause the stream object to be
garbage collected. Therefore, the object must not still be hanging on
to the wchar_t * string, which was already transferred to the string
object.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The --free-all feature is broken. It is needed for confirming
lack of memory leaks during development. What breaks it is the
atexit call to run_load_hooks in eval.c, which occurs after
the atexit call to free_all in txr.c which blows everything
away.
* Makefile (tst/tests/019/load-hook.ok): Let's put --free-all
on this test case, because it has to with the load hooks.
Make no mistake though: everything crashes with --free-all,
not this test case specifically.
* txr.c (opt_free_all): New global variable.
(free_all): Free resources only if opt_free_all is true.
Lose the paranoid called flag.
(main): Register free_all with atexit before callilng init.
This ensures that it will be called after any atexit
handlers registered as part of init, like the one in sysif.c
and eval.c.
(txr_main): The --free-all option now just sets opt_free_all.
* txr.h (opt_free_all): Declared.
|
|
|
|
| |
* txr.1: Add missing "If" at start of sentence.
|
|
|
|
|
|
|
|
|
|
|
| |
* parser.c (open_txr_file): Use liberal heaps of #if HAVE_ZLIB.
If there is no Zlib, and the caller explicitly requests a
.tlo.gz file to be loaded, then throw. Do not implicitly look
for a .tlo.gz file.
* stream.c (open_file): #if HAVE_ZLIB around a goto label that
is only used out of HAVE_ZLIB code, to eliminate unused label
warning.
|
|
|
|
|
|
| |
* stream.c (parse_mode, open_file, open_fileno): Since self
is a string, use ~a to print it, or else quotes
will appear.
|
|
|
|
|
|
|
|
|
|
|
|
| |
* RELNOTES: Updated.
* configure (txr_ver): Bumped version.
* stdlib/ver.tl (lib-version): Bumped.
* txr.1: Bumped version and date.
* txr.vim, tl.vim: Regenerated.
|
|
|
|
|
|
|
| |
* chksum.c (crc32): Stop-gap solution: make it static.
Also, fix wrong self-string.
* chksum.h (crc32): Declaration removed.
|
|
|
|
| |
* inst.nsi: pull in cygz.dll.
|
|
|
|
|
|
|
|
|
|
| |
* stream.c (sh): Use a single definition for this function,
which uses the shell and shell_arg variables to use
either /bin/sh -c or cmd.exe /c. We only want to use
cmd.exe when running as a Windows native program on Cygnal.
* tests/018/process.tl: Remove workaround from test case.
This is what was causing the weirdness.
|
|
|
|
| |
* gzio.c (gzio_set_prop): Remove unused ops variable.
|