Skip to content

Instantly share code, notes, and snippets.

View sebres's full-sized avatar
🛠️
WiP

Sergey G. Brester sebres

🛠️
WiP
View GitHub Profile
@sebres
sebres / tcl-re-engine-non-greedy--quadratic-O-illustration.md
Last active November 12, 2024 22:16
Non-greedy catch-all in Tcls NFA seems to have O(n**2)

Non-greedy catch-all in Tcls NFA seems to have quadratic time complexity (O(n**2)), see the comparision (greedy vs. non-greedy) for 1st and 2nd sub-REs (.*) and (.*?) below.

Explanation: a growth of n (length of matched part, e. g. from 500 to 5000 chars) by a factor of 10 increases the time of evaluation by a factor of 100 (452µs vs 40598µs).

Note that the whole RE is anchored from both sides, so the greedyness even doesn't really matter here (the result of match will be the same in any case).

The 3rd RE is added for the illustration, that NFA seems not even consider the next RE (\s+ which shall definitely match) in case of slow non-greedines, unless added explicitely, like in (.*?(?=\s)), what then immedially switches to linear complexity O(n).

@sebres
sebres / result.diff
Last active January 29, 2024 11:02
Result illustrating the regression of Tcl_ReadChars in absence of append (doubling of bytes in internal object used for read on every iteration), bug [da16d15574]
diff --git "a/result-org.txt" "b/result-fix.txt"
--- "a/result-org.txt"
+++ "b/result-fix.txt"
% # with 4KB buffersize:
% setup { set ch [::tclTestPerf-Chan::_get_test_chan 4096]; fconfigure $ch -buffersize }
4096
% # 10 * 1M:
% read $ch [expr {int(1e6)}]
-6757.00 µs/# 10 # 147.99 #/sec 67.570 net-ms
+36189.9 µs/# 10 # 27.632 #/sec 361.899 net-ms
@sebres
sebres / actions.md
Last active August 16, 2023 11:21
fail2ban - simple actions supplying iptables / ipset to remote host

action.d/ssh-iptables.conf:

## Usage:
##   banaction = ssh-iptables[[email protected], type=multiport]
##   banaction_allports = ssh-iptables[[email protected], type=allports]

[INCLUDES]

before = iptables.conf
@sebres
sebres / sql-not-in-test.tcl
Last active July 29, 2022 17:26
PoC -- NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL (mariadb vs. sqlite3)
proc prepare {type args} {
set sp "CREATE TEMPORARY TABLE pages ( type VARCHAR(20), id VARCHAR(10), content varchar(50), PRIMARY KEY (type, id) )"
set spd "CREATE TEMPORARY TABLE pages_done ( type VARCHAR(20), id VARCHAR(10), PRIMARY KEY (type, id) )"
switch -- $type {
mysql {
package require tdbc::mysql
append sp " ENGINE = MEMORY"; append spd " ENGINE = MEMORY";
tdbc::mysql::connection create db {*}$args
}
sqlite3 {
@sebres
sebres / PoC-time-jumps.sh
Last active August 22, 2022 13:54
PoC-time-jumps.sh -- proof of concept to detect FPU/hardware related issues causing time jump in python (fail2ban/fail2ban#3187)
#! /bin/sh
printf '%s' '
#include <inttypes.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
@sebres
sebres / detect-inv-chars.tcl
Last active November 5, 2021 19:45
detect-inv-chars.tcl -- detect invisible chars in files or directories
#!/usr/bin/env tclsh
# -------------------------------------------------------------------------
# Script to detect following zero-width or invisible characters:
#
# LRE U+202A RLE U+202B LRO U+202D RLO U+202E LRI U+2066 RLI U+2067 FSI U+2068 PDF U+202C PDI U+2069
# ZWS U+200B ZWNJ U+200C ZWJ U+200D ZWNBSP U+FEFF
#
# Copyright (c) 2016-2020 by Sergey G. Brester aka sebres
# -------------------------------------------------------------------------
@sebres
sebres / parseUAG.tcl
Created October 26, 2021 16:47
parseUAG.tcl -- example how to parse user agents (in tcl)
proc parseUAG {uag} {
array set a {cltype "" clver "" os "" plat "" safari 0 ffox 0 chrome-compat 0 webkit-compat 0}
if {![regexp {^(\w+)/(\d+(?:\.\d+){0,4})\s+\((?:(\w+);(?:\s*U;)?\s*)?(\w+)\s*(\d+(?:\.\d+){0,4})} $uag _ a(cltype) a(clver) a(os) a(plat)]} {
regexp {^(\w+)/(\d+(?:\.\d+){0,4})\M} $uag _ a(cltype) a(clver)
if {![regexp {\((\w+);(?:(?:\s*U;)?\s*)?(\w+)\s*(\d+(?:\.\d+){0,4})} $uag _ a(os) a(plat)]} {
regexp {\((\w+);\s*(?:CPU\s+(\w+)\s+)?(?:OS\s+(\S+)\s+)(?:like\s+([^)]+))\)} $uag _ a(plat) a(cpu) a(osver) a(osdesc)
}
}
regexp {\mChrome/(\d+(?:\.\d+){0,4})} $uag {} a(chrome-compat)
regexp {\mAppleWebKit/(\d+(?:\.\d+){0,4})} $uag {} a(webkit-compat)
@sebres
sebres / embedeval.c
Created September 30, 2021 10:29
embedeval.c -- example of tcl-code embedding
/*
* embedeval.c -- example of tcl-code embedding
*
* Compile:
* mingw: gcc -O2 -DUSE_TCL_STUBS=1 -I$tcl/win -I$tcl/generic embedeval.c -shared -o embedeval.dll libtclstub86.a
* *nix: gcc -O2 -DUSE_TCL_STUBS=1 -I$tcl/unix -I$tcl/generic embedeval.c -shared -o embedeval.so libtclstub86.a
*
* Usage:
* $ tclsh86
* % load embedeval
@sebres
sebres / bot-bridge-nicks.lua
Last active June 1, 2021 13:19
bot-bridge-nicks.lua -- HexChat plug-in to wrap IRC bots to real user nicknames
hexchat.register("bot-bridge-nicks", "0.1", "Rewrites messages of bots to display bridge users as IRC users")
-- ijchain, ischain, liberachain are bridges:
botspattern = {"i.*chain", "^[<«](.-)[>»] (.*)$", "^<?(.-)>? (.*)$"}
botspattern2 = {"l.*chain", "^[<«](.-)[>»] (.*)$", "^%* (.-) (.*)$"}
local function fullname(user, nick)
return user:gsub("%s+", "-").."!"..user:gsub("%s+", "_").."@behind.the.bridge/"..nick
end
@sebres
sebres / cm.tcl
Created October 9, 2020 12:40
cm.tcl -- rich (data mining & science) console mode example (shorten, wrap or suppress an output return value in tcl)
proc cm args {
array set in {-out auto}
array set in $args
set scr ""
puts -nonewline "%cm% "; flush stdout
while {[gets stdin line] >= 0 && ($line ni {/cm /exit} || $scr ne "")} {
append scr $line "\n"
if {![info complete $scr]} {
puts -nonewline " ... "; flush stdout
continue