summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* Version 282.txr-282Kaz Kylheku2022-09-166-1073/+1109
| | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated.
* nan-boxing: make default on 64 bit.Kaz Kylheku2022-09-161-2/+1
| | | | | * configure: automatically select NaN boxing on 64 bit platforms.
* nan-boxing: warning fix for gcc 12.Kaz Kylheku2022-09-161-0/+2
| | | | | | | | | | gcc 12.2.0, targetting RISC-V, emitted a warning for the c_f function that the &u expression uses an uninitialized u, even though u is declared with an initializer. Code builds otherwise and tests pass. * lib.h (c_f): Also suppress and re-enable the -Wuninitialized option.
* doc: notes about boxing of numbers.Kaz Kylheku2022-09-161-0/+38
| | | | | | | * txr.1: In the Numbers section, talk about fixnum and bignum, and the boxed/unboxed terminology, as well as the possibility that floating-point may be unboxed, and how to detect that.
* nan-boxing: build on older gcc.Kaz Kylheku2022-09-162-14/+16
| | | | | | | | | | | | Older GCC 4.x versions do not support diagnostic pragmas in functions and don't have push pragmas for diagnostics. * arith.c (flo): Put the diagnostic disabling pragma stuff outside of the function. Instead saving and restoring the status with push and pop, we just disable the aliasing warning and re-instate it as a warning. * lib.h (c_f): Likewise.
* seq-iter: bugfix: floating-point ranges.Kaz Kylheku2022-09-152-24/+71
| | | | | | | | | | | | | | | | | | | | | | * lib.c (seq_iter_get_range_bignum): Static function renamed to seq_iter_get_range_number because it in fact generalizes to numbers. (seq_iter_peek_range_bignum): Renamed to seq_iter_peek_range_number. (seq_iter_get_rev_range_bignum): Renamed to seq_iter_get_rev_range_number. (seq_iter_peek_rev_range_bignum): Renamed to seq_iter_peek_rev_range_number. (si_range_bignum_ops): Renamed to si_range_number_ops. (si_rev_range_bignum_ops): Renamed to si_rev_range_number_ops. (seq_iter_init_with_info): Handle ranges where the from value is floating-point. Also, if the from-value is bignum that fits into cnum range, we now try to handle that as a cnum range. * tests/012/iter.tl: New tests.
* compiler: bug: bad basic-block merge across end insn.Kaz Kylheku2022-09-154-6/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The bad situation reproduced as a miscompilation of some prof forms at *opt-level* 5 or above. The basic idea is that there is a situation like this prof t2 ... profiled code here producing value in t8 mov t2 t8 end t2 end t2 The code block produces a value in t8, which is copied into t2, and executes the end instruction. This instruction does not fall through to the next one but passes control back to the prof instruction. The prof instruction then stores the result value, which came from t2, back into the t2 register and resumes the program at the end t2. The first bad thing that happens is that the end instructions get merged together into one basic block. The optimizer then treats them without regard for the prof instruction, as if they were a linear sequence. It looks like the register move mov t2 t8 is wasteful and so it eliminates it, rewriting the end instruction to: end t8 end t8 Of course, the second instruction is now wrong because prof is still producing the result in t2. To fix this without changing the instruction set, I'm introducing another pseudo-op that represents end, called xend. This is similar to jend, except that jend is regarded as an unconditional branch whereas xend isn't. The special thing about xend is that a basic block in which it occcurs is marked as non-joinable. It will not be joined with the following basic block. * stdlib/asm.tl (xend): New alias opcode for end. * stdlib/compiler.tl (comp-prof): Use xend to end prof fragment, rather than plain end. * stdlib/optimize.tl (basic-block): New slot, nojoin. If true, block cannot be joined with next one. (basic-blocks jump-ops): Add xend to list of jump ops, so that a basic block will terminate on xend. (basic-blocks link-graph): Set the nojoin flag on a basic block which contains (and thus ends with) xend. (basic-blocks local-liveness): Add xend to the case in def-ref that handles end. (basic-blocks (peephole, join-blocks)): Refuse to join blocks marked nojoin. * tests/019/comp-bugs.tl: New file with miscompiled test case that was returning 42 instead of (42 0 0 0) as a result of the wrong register's value being returned.
* compiler: bug: scoping of lambda optionals.Kaz Kylheku2022-09-152-17/+20
| | | | | | | | | | | | | | | | | | | | | | The scoping is not behind handled correctly for optional variables. The init-forms are being evaluated in a scope in which all the variables are already visible, instead of sequentially. Thus, for instance, variable rebinding doesn't work, as in (lambda (: (x x)) ...). When the argument is missing, x ends up with the value : because the expression refers to the new x, rather than the outer x. * stdlib/compiler.tl (compiler comp-lambda-impl): Perform the compilation of the init-forms earlier. Use the same new trick that is used for let*: the target for the code fragment is a locaton obtained from get-loc, which is then attached to a variable afterward. The spec-sub helper is extended with a loc parameter to help with this case. * tests/012/lambda.tl: New test case that fails without this fix.
* build: remove .tlo.tmp file before compiling.Kaz Kylheku2022-09-151-0/+1
| | | | | | | | | * Makefile (COMPILE_TL): Before we invoke txr --compile, let's make sure there isn't a .tmp file left over by a previous failed compile job. Otherwise --compile will consider that to be an up-to-date compiled file due to its newer timestamp relative to the .tl file, and we end up renaming that to .tlo.
* compiler: eliminate rename-var hack.Kaz Kylheku2022-09-151-13/+6
| | | | | | | | | | | | | | | * stdlib/compiler.tl (env rename-var): Method removed. (compiler comp-let): Instead of initially creating a let* variable as a gensym, and then renaming it after compiling the init expression, we now just obtain the location not bound to a variable, use the location when compiling the init form, and bind the location to a variable right after. This is cleaner since the only thing we are mutating now is the environment, and we are not wastefully allocating a gensym. The real motivation is that this is building up to a bugfix in compiling optional variables in lambda: stay tuned!
* compiler: unbundle v-reg allocation from env extensionKaz Kylheku2022-09-151-6/+10
| | | | | | | | | | | | * stdlib/compiler.tl (env get-loc): New method for allocating v-reg, split out of extend-var and extend-var*. Now there is a check for the v-cntr overflow. (env (extend-var, extend-var*)): Taken an optional loc parameter, so the caller can optionally allocate a v-reg location using get-loc, and then specify that location when creating a variable. If the argument is omitted, use get-loc.
* compiler: eliminate uses of cdar.Kaz Kylheku2022-09-141-7/+9
| | | | | | | | | * stdlib/compiler.tl (env (extend-var, extend-var*)): Return the variable binding rather than the alist containing it. (compiler (comp-catch, comp-let, comp-tree-case)): Drop use of cdar on return value of extend-var to ferret out the binding from the alist.
* compiler: test for recent bugfix.Kaz Kylheku2022-09-141-0/+2
| | | | | | * tests/012/lambda.tl: Add the test case which reproduces the compiler failure that was fixed several commits ago.
* nan-boxing: use GCC pragmas to disable aliasing warnings.Kaz Kylheku2022-09-143-18/+14
| | | | | | | | | | | * arith.c (flo): The line of code which triggers the aliasing diagnostic is wrapped with GNU-C-specific pramgas that disable the diagnostic just for that line. * lib.h (c_f): Likewise. * configure: Drop the test which adds -Wno-strict-aliasing to the DIAG_FLAGS;
* compiler: bugfixes in dead code eliminationKaz Kylheku2022-09-131-2/+2
| | | | | | | | | | | | | | | | | | | | | | * stdlib/optimize (basic-blocks ling-graph): I'm reverting an old design decision here. The decision is this: the basic block of a close instruction points to the first basic block of the closure as its next block, but that next block does not point back: it doesn't list the close instruction's basic block among the rlinks. The idea was that the close instruction doesn't jump to that block, and so it shouldn't be linked to it. However, the next link was set purely so that the graph is connected. Unfortunately, the inconsistency in the graph structure which this causes is a problem in the elim-dead-code method. A situation arises when that first basic block after the close is removed. Because pit has an empty rlinks list, the block remains listed as the next block of the close block, even though it is removed from the master list of blocks. (basic-blocks check-bypass-empty): Fix one forgotten detail in this function: the block being deleted must be removed from the rlinks list of the next block.
* configure: fix disabling NaN boxing on 32 bit.Kaz Kylheku2022-09-131-2/+3
| | | | | * configure: actually disable it, don't just print the warning. Warning should say 64 bits required, not 32.
* Implement NaN boxing.Kaz Kylheku2022-09-139-76/+347
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On platforms with 64 bit pointers, and therefore 64-bit-wide TXR values, we can use a representation technique which allows double floating-point values to be unboxed. Fixnum integers are reduced from 62 bits to 50, and there is a little more complexity in the run-time type checking and dispatch which costs extra cycles. The support is currently off by default; it must be explicitly enabled with ./configure --nan-boxing. * lib.h (NUM_MAX, NUM_MIN, NUM_BIT): Define separately for NaN boxing. (TAG_FLNUM, TAG_WIDTH, NAN_TAG_BIT, NAN_TAG_MASK, TAG_BIGMASK, TAG_BIGSHIFT, NAN_FLNUM_DELTA): New preprocessor symbols. (enum type, type_t): The FLNUM enumeration constant moves to just after LIT, so that its value is the same as TAG_FLNUM. (struct flonum): Does not exist under NaN boxing. (union obj): No fl member under NaN boxing. (tag, is_ptr): Separately defined for NaN boxing. (is_flo): New function under NaN boxing. (tag_ex): New function. It's like tag, but identifies floating-point values as TAG_FLNUM. The tag function continues to map them to TAG_PTR, which is wrong under NaN boxing, but needed in order not to separately write tons of cases in the arith.c module. (type): Use tag_ex, so TAG_FLNUM is handled, if it exists. (auto_str, static_str, litptr, num_fast, chr, c_n, c_u): Different definition for NaN boxing. (c_ch, c_f): New function. (throw_mismatch): Attribute with NORETURN. (nao): Separate definition for NaN boxing. * lib.c (seq_kind_tab): Reorder initializer to follow enum reordering. (seq_iter_rewind): use c_n and c_ch functions, since type checking has been done in those cases. The self parameter is no longer needed. (iter_more): use c_ch on CHR object. (equal): Use c_f accessor to get double value rather than assuming there is a struct flonum representation. (stringp): Use tag_ex, otherwise a floating-point number is identified as TAG_PTR. (diff, isec, isecp): Don't pass removed self parameter to seq_iter_rewind. * arith.c (c_unum, c_dbl_num, c_dbl_unum, plus, minus, signum, gt, lt, ge, le, numeq, logand, logior, logxor, logxor_old, bit, bitset, tofloat, toint, width, c_num, c_fixnum): Extract floating-point value using c_f accessor. Handle CHR type separately from NUM because the storage representation is no longer identical; CHR values have a two bit tag over bits where NUM has ordinary value bits. NUM is tagged at the NaN level with the upper 14 bits being 0xFFFC. The remaining 50 bits are the value. (flo): Construct unboxed float under NaN boxing by taking image of double as a 64 bit value, and adding the delta offset, then casting to the val pointer type. (c_flo): Separate implementation for NaN boxing. (integerp, numberp): Use tag_ex. * buf.c (str_buf, buf_int): Separate CHR and NUM cases, like in numerous arith.c functions. * chksum.c (sha256_hash, md5_hash): Use c_ch accessor for CHR value. * hash.c (equal_hash, eql_hash): Handle CHR separately. Use c_f accessor for floating-point value. (eq_hash): Use tag_ex and handle TAG_FLNUM value under NaN boxing. Handle CHR separately from NUM. * ffi.c (ffi_float_put, ffi_double_put, carray_uint, carray_int): Handle CHR and NUM separately. * stream.c (formatv): Use c_f accessor. * configure: disable automatic selection of NaN boxing on 64 bit platforms, for now. Add test whether -Wno-strict-aliasing is supported by the compiler, performed only if NaN boxing is enabled. We need to disable this warning because it goes off on the code that reinterprets an integer as a double and vice versa.
* Define bit width of NUM type in one place.Kaz Kylheku2022-09-123-14/+11
| | | | | | | | | | | | * lib.h (NUM_BIT): New preprocessor symbol. * arith.c (CNUM_BIT): Preprocessor symbol removed; this same quantity is already known as PTR_BIT in lib.h. (mul, square): Replace CNUM_BIT with PTR_BIT. (comp_trunc, logtrunc, sign_extend, ash): Replace num_bits with NUM_BIT. * struct.c (struct_inst): Replace calculation with NUM_BIT.
* Reduce proliferation of TAG_SHIFT.Kaz Kylheku2022-09-123-12/+12
| | | | | | | | | | | * arith.c (num_to_buffer, c_unum, c_dbl_num, c_dbl_unum, c_num, c_fixnum): Use c_n inline function instead of open coding exactly the same thing. * lib.c (c_chr): Likewise. * struct.c (make_struct_type, lookup_slot, lookup_static_slot_desc, static_slot_p): Likewise.
* configure: config groundwork for NaN boxingKaz Kylheku2022-09-121-0/+28
| | | | | | | | | * configure (nan_boxing, nan_boxing_given): New variables. New help text for nan-boxing option. New test which sets nan-boxing if pointers are 64 bits, and also checks for nan-boxing wrongly being forced on a 32 bit target. Generate CONFIG_NAN_BOXING symbol in config.h.
* doc: format: missing details about precision.Kaz Kylheku2022-09-111-18/+57
| | | | | | | | | * txr.1: Document how ~a and ~s calculate the effective precision for the second step for integer and floating-point values, adding a Rationale paragraph about why it's different between the two in the case of zero or missing width.
* doc: document [. expr] support.Kaz Kylheku2022-09-101-0/+28
| | | | | * txr.1: Document and advise users that it doesn't work in 281 or older versions.
* syntax: read and print [. x] and [. @x].Kaz Kylheku2022-09-084-1163/+1216
| | | | | | | | | | | | | | | | | | | | | | | * lib.c (obj_print_impl): Handle (dwim . atom) syntax by printing [. atom]. Note that (dwim . @var) and (dwim . @(expr)) already print as [. @var] and [. @(expr)]; this is not new. But none of these forms are supported by reading without the accompanying change to the parser. * parser.y (dwim): Handle the [. expr] and [ . expr] syntax, so that forms like [. a] and [. @a] have print-read consistency. The motivation is to be able to [. @args] in pattern matching to match a DWIM forms; I tried that and was surprised to have it blow up in my face. * tests/012/readprint.tl: New test file. Future printer/parser changes will be tested here. Historically, changes to the syntax have not been consistently unit-tested. * y.tab.c.shipped: Regenerated.
* Version 281.txr-281Kaz Kylheku2022-09-035-147/+176
| | | | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated. * protsym.c: Regenerated.
* vim: fix for #; commented JSON.Kaz Kylheku2022-09-021-0/+1
| | | | | | | * genvim.txr (txr_ign_json): Assign to Comment category, otherwise only the start and end markers, and interior bracketed material, is colored as a comment, with other top-level items showing white.
* vim: simplify #; regions.Kaz Kylheku2022-08-311-16/+13
| | | | | | | | | * genvim.txr (txr_ign_par, txr_ign_bkt, txr_ign_tok): Regions placed under one name, txr_ign. (list): Updated to include just txr_ign. (txr_ign_par_interior,txr_ign_bkt_interior, txr_ign_bra_interior): All combined under one name. (txr_ign, txr_ign_json): Refer to just txr_interior.
* vim: improve #; commenting of JSON.Kaz Kylheku2022-08-311-9/+13
| | | | * genvim.txr: Changes to extend #; over JSON.
* vim: improvement in #; comment.Kaz Kylheku2022-08-301-3/+2
| | | | | | | * genvim.txr (txr_ign_par, txr_ign_bkt): Add ^ and @ as valid prefix characters so brackets or parens preceded by these are commented out. Remove redundant txr_ign_bkt region that is identical to the previous line.
* close-lazy-streams: test.Kaz Kylheku2022-08-301-0/+3
| | | | * tests/018/close-lazy.tl: New file.
* txr: test for new @(next) behaviors.Kaz Kylheku2022-08-302-0/+17
| | | | | | * tests/018/noclose.txr: New file. * tests/018.noclose.expected: New file.
* vim: deal with bvars and square brackets.Kaz Kylheku2022-08-301-2/+3
| | | | | | | | | | | | The last round of changs. The txr_bracevar group is still handling bracket vars in their entirety, including the @. Also square bracket lists are not handled right. * genvim.txr (txr-elem): Add txr_bracket and txr_bracevar. (txr_bracevar): Don't match @ sigil, and mark as contained group.
* vim: fix quasiliterals.Kaz Kylheku2022-08-301-4/+6
| | | | | | | | | | | | | | | | | | | | The previous commit breaks the syntax coloring of the interior of quasiliterals. That is now addressed. * genvim.txr (txr-qelem): New variable holding the elements of a quasiliteral which follow the @ sigil. These items were previously listed as the contained items of txr_quasilit. Now they become nextgroup elements of tl_qat. (tl_qat): New match group representing the special items in a quasiliteral. It matches the sigil, and then the txr-qelem items via nextgroup. (tl_bracevar): Renamed to txr_qbracevar, since it targets the brace variable variant contained in quasiliterals. (txr_mlist,txr_mbracket): No longer used; removed. (txr_quasilit): Now just contains txr_qat.
* vim: tweak @ handling.Kaz Kylheku2022-08-301-24/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I noticed that in some Vim color schemes, the @ in @( ) is colored the same as the parentheses, whereas in @abc, it is colored differently from the identifier (and different from parentheses). This patch fixes things so that the @ sigil is in the Special category, rather than Delimiter, almost everywhere. * genvim.txr (txr-elem): New variable, for holding names of regions which follow the @ in the TXR language. Used in definition of txr_at. (bvar, dir, list): Remove the txr_mlist and txr_mbracket regions. (txr_at): New match group defined, which matches the @ sigil in TXR, followed by various elements using the nextgroup mechanism. txr_at is already assigned to a highlight category via a previously dangling entry. (txr_error,txr_atat,txr_comment,txr_contin, txr_char,txr_error,txr_char,txr_regdir,txr_variable, txr_splicevar,txr_metanum,txr_directive): These match groups don't match the leading @ sigil any more and are marked contained. They activate as the nextgroup items in txr_at, allowing them to be colored differently. (tl_error): New group. split off from txr_error. We don't want to to recognize this category after the @ in TXR because @#... is the old-style comment. (tl_ident): Don't try to match leading @. This is useless because there is a more specific match via txr_metaat later. (txr_quote, txr_metaat): Mark these not contained in Lisp so they activate at the top level. (txr_directive): Don't match leading @. This now activates as a nextgroup item in txr_at. Thus directives can have a differently colored @. (txr_mlist, txr_mbracket): These are now unconditionally contained, and are used only in txr_quasilit. I am otherwise leaving quasiliterals alone in this patch; it will need the same treatment for @ to be colored seprately inside quasiliterals.
* txr: close streams.Kaz Kylheku2022-08-293-18/+77
| | | | | | | | | | | | | | | | | | | * match.c (noclose_k): New keyword variable. (v_next_keys, v_output_keys): New static variables. (v_next_impl): Use v_next_keys in calculating alist, rather than freshly allocating it each time. Check for the new :noclose keyword; if it is missing, close any locally opened stream when done. (v_output): Refer to v_output_keys precalculated list rather than allocating it every time. (match_files): If a stream is opened in by a call to open_data_source from this function, then the stream is closed when this function returns. (syms_init): Intern the :noclose symbol. (plist_keys_init): New function. (match_init): Call plist_keys_init. * txr.1: Documented new :noclose option of @(next).
* New macro: close-lazy-streams.Kaz Kylheku2022-08-287-1/+102
| | | | | | | | | | | | | | | | | | | | | | | | * lib.c (lazy_stream_s): New symbol variable. (lazy_streams_binding): New static variable. (lazy_stream_register): New static function (lazy_stream_cons): If the stream is associated with a lazy cons, register it with lazy_stream_register. (obj_init): gc-protect lazy_streams_binding variable. Intern the sys:*lazy-streams* symbol. * lib.h (lazy_streams_s): Declared. * eval.c (eval_init): Register sys:*lazy-streams* special variable. * stdlib/getput.tl (close-lazy-streams): New macro. * autoload.c (getput_set_entries): Trigger autload on close-lazy-streams symbol. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
* New function: search-allKaz Kylheku2022-08-176-9/+100
| | | | | | | | | | | | | | | | | | | | | | | * eval.c (eval_init): search-all intrinsic registered. * lib.c (search_common): New Boolean argument all, indicating whether all positions are to be returned. We must handle this in the two places where empty key and sequence are handled, and also in the main loop. A trick is used: the found variable is now bound by list_collect_decl, but not used for collecting unless all is true. (search, rsearch, contains): Pass 0 for all argument of search_common. (search_all): New function. * lib.h (search_all): Declared. * tests/012/seq.tl: New tests. * txr.1: Documented. * stdlib/doc-syms.tl: Regenerated.
* search/rsearch: some test cases.Kaz Kylheku2022-08-171-0/+36
| | | | * tests/012/seq.tl: New tests.
* ffi: check for out-of-range wchar_t.Kaz Kylheku2022-08-131-0/+3
| | | | | | * ffi.c (ffi_wchar_get): Reject wchar_t values that are negative or beyond U+10FFFF; do not convert these to a character.
* Version 280.txr-280Kaz Kylheku2022-08-094-5/+20
| | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date.
* build: handle hard link failure in make install.Kaz Kylheku2022-08-091-1/+1
| | | | | | | | | * Makefile (HARDLINK): Print a diagnostic if the link command fails and ignore the situation. Hard links are restricted on Android. On that platform, txr being available under the names txrlisp and txrvm is likely of limited utility, so we won't waste space by making copies of the executable.
* listener: bug: history ignored if .txr_profile doesn't exist.Kaz Kylheku2022-08-091-1/+1
| | | | | | * parser.c (repl): Fix code wrongly checking for the existence of the .txr_profile file as a condition for loading .txr_history. It should of course be checking for .txr_history.
* load: fix misleading error message.Kaz Kylheku2022-08-091-1/+1
| | | | | * parser.c (open_txr_file): Replace "not found" wording with "unable to open" because the diagnostic covers permission errors.
* Version 279.txr-279Kaz Kylheku2022-08-086-1051/+1095
| | | | | | | | | | | | * RELNOTES: Updated. * configure (txr_ver): Bumped version. * stdlib/ver.tl (lib-version): Bumped. * txr.1: Bumped version and date. * txr.vim, tl.vim: Regenerated.
* path-components-safe: proc tests only on Linux.Kaz Kylheku2022-07-301-18/+20
| | | | | | | * 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.
* path-components-safe: check symlink link count.Kaz Kylheku2022-07-301-2/+3
| | | | | | * 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.
* path-components-safe: tighten /proc checkKaz Kylheku2022-07-302-45/+35
| | | | | | | | | | | | | | 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.
* path-components-safe: handle consecutive slashes.Kaz Kylheku2022-07-301-4/+2
| | | | | * stdlib/path-test (path-components-safe): Remove empty components from split path.
* path-components-safe: repel /proc symlink attacksKaz Kylheku2022-07-292-17/+67
| | | | | | | | | | | | | | | | | | | | | | 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.
* rel-path, path-equal: relocate.Kaz Kylheku2022-07-293-107/+96
| | | | | | | | * 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.
* stringp: rewrite.Kaz Kylheku2022-07-281-5/+13
| | | | | | * 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.