fuzzball-muck / fuzzball Goto Github PK
View Code? Open in Web Editor NEWOngoing development of the Fuzzball MUCK server software and associated functionality.
License: Other
Ongoing development of the Fuzzball MUCK server software and associated functionality.
License: Other
Compiled with MUD_ID
and MUD_GID
set in include/config.h
. MUCK is configured to listen on port 23 for unencrypted connections. Launch fails with the following error recorded in logs/fbmuck.err
:
binding stream socket: Permission denied
Player named "Test" is contained in "Room A." An action named "Test" is located on room zero, Room A's parent room. "Test" match
is returning the action, not the player, even when executed in Room A. I believe the player should be matched in this case, as it is the more local object.
Note: I have replicated this issue on FurryMUCK as well as SPR, indicating that this has existed for some time.
A MUF program that does something like:
: main begin 0 try prog #1 "foo" interp pop catch pop endcatch repeat ;
can stall the MUCK for a very, very long time with just M3 permissions. A similar program using TESTLOCK can stall the MUCK for a very, very long time with only M1 permissions.
We enforce a limit of 8 levels of nesting, but given the default PREEMPT instruction limit of 10k, this allows:
which might as well not be an instruction limit, even with a rather modest level of nesting.
One fix would be to limit total instructions executed recursively by any interp_loop() call (at least for non-M4 code). Another approach would be to limit the total number of interp_loop() calls, not just the number of levels of interp_loop() calls.
I could've sworn I saw reasonably complete documentation for what the YIELD and OVERT flags did, once, but I can't find it any more. The best I've been able to come up with is a couple of comments in the middle of src/match.c. They're certainly not documented in the online help with the other user-visible flags, which is something that needs fixing ASAP.
Testing has revealed that FB7 supports ECDH key agreement, but not traditional modulo-based DH key agreement. While ECDH is superior in many aspects, it's entirely possible (perhaps even likely) that some TLS v1.0-only clients support DH while lacking support for ECDH. Enabling this support might go a long way toward eventually being able to disable the (now deprecated/insecure) RSA encryption-based cipher modes.
Tested using tf5.0b8 on CentOS 7.
Configured a test MUCK using the following SSL preference:
aRSA+EECDH+AESGCM:aRSA+EDH+AESGCM:aRSA+EECDH+AES+SHA384:aRSA+EECDH+AES+SHA256:aRSA+EDH+AES+SHA384:aRSA+EDH+AES+SHA256:aRSA+EECDH+AES+SHA1:aRSA+EDH+AES+SHA1:aRSA+AESGCM:aRSA+AES+SHA384:aRSA+AES+SHA256:aRSA+AES+SHA1:!SRP:!PSK
$ openssl ciphers 'aRSA+EECDH+AESGCM:aRSA+EDH+AESGCM:aRSA+EECDH+AES+SHA384:aRSA+EECDH+AES+SHA256:aRSA+EDH+AES+SHA384:aRSA+EDH+AES+SHA256:aRSA+EECDH+AES+SHA1:aRSA+EDH+AES+SHA1:aRSA+AESGCM:aRSA+AES+SHA384:aRSA+AES+SHA256:aRSA+AES+SHA1:!SRP:!PSK' | tr ':' '\n'
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-SHA384
ECDHE-RSA-AES128-SHA256
DHE-RSA-AES256-SHA256
DHE-RSA-AES128-SHA256
ECDHE-RSA-AES256-SHA
ECDHE-RSA-AES128-SHA
DHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA
AES256-GCM-SHA384
AES128-GCM-SHA256
AES256-SHA256
AES128-SHA256
AES256-SHA
AES128-SHA
Attempting to connect to the test MUCK succeeds using the ECDHE-RSA-AES256-GCM-SHA384
cipher suite.
Appending !EECDH
to the end of the cipher preferences string, restarting the MUCK, and reattempting the connection succeeds using the AES256-GCM-SHA384
cipher suite, which is the highest-preference (obsolete) RSA encryption mode specified in the cipher preferences.
Performing the same tests against a web server causes tf to connect to the web server using the DHE-RSA-AES256-GCM-SHA384
cipher suite, which is the legacy-but-still-secure MODP-based Diffie-Hellman key agreement mode.
MUF arithmetic operations +
, -
, bitshift
allow overflow/underflow to happen or bitshifts which are larger than the size of an integer. For +
and -
, they detect when this produces the wrong result and set the err_ibounds? flag. For bitshift
, they do not. In all cases, the implementations will invoke undefined behavior.
For bitshift, the result in practice of shifting by more than the width of the integer type varies; sometimes the the result is 0 or -1 as expected, but sometimes the shift amount is truncated based on the maximum possible shift amount instead.
In the case of +
and -
, this usually works out to wrapping around in twos complement, which is probably the behavior we expect, but this is not guaranteed without something like the GCC flag -fwrapv
.
For the most part, the floating point primitives for MUF handle floating point errors in a non-IEEE way. Typically, they return (positive) INF or 0 on an error and set error flags which can be tested with err_fbounds? err_divzero?, etc. They rarely expose NaN, even though there are FIXMEs in the C code about doing so (e.g. in prim_sin).
Some primitives, however, expose the native NaNs:
inf inf fmod
is NaN)Some kinds of errors that result in infinity that do not set err_fbounds?, err_imaginary?, etc.:
diff3
dist3d
These differences in handling are not documented and seem unintentional.
Proto apparently has an @tune
to use IEEE inf/nan instead of trying to convert nans into 0s, which would be a saner approach than making NaNs 0s, but probably not something we can do as our only implementation unless we don't mind breaking some backwards compatibility.
The MUF program
: main { "foo" 0.0 "bar" 0.0000001 "quux" 0.01 "delta" 0.00000000001 }dict 1 array_nunion ;
enters an infinite loop. This is related to #179.
Server-side TCP keepalives can help, but we have a few players that need client-side keepalive capability. I'd like to see a command or a tuneable value that lets us set a command that a player can trigger via client-side timer that generates regular network activity, but does NOT reset their WHO idle time.
Something like 2147483647 1 +
can overflow without making err_ibounds?
true when the optimize_muf
@tune
is set. This is because the constant folding performed in OptimizeIntermediate
does not check for overflow.
Debian 9.3, OpenSSL 1.1.0f-3+deb9u1, GCC 6.3.0-4.
~/src$ git clone https://github.com/fuzzball-muck/fuzzball.git
Cloning into 'fuzzball'...
remote: Counting objects: 7582, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 7582 (delta 0), reused 1 (delta 0), pack-reused 7579
Receiving objects: 100% (7582/7582), 6.78 MiB | 0 bytes/s, done.
Resolving deltas: 100% (5223/5223), done.
~/src$ cd fuzzball/
~/src/fuzzball$ ./configure --with-ssl --enable-ipv6
TinyMUCK fb7.x auto-configure script.
This script will try and determine things about your system so
that FB can compile correctly. This will create your Makefile
and the header file autoconf.h in the include directory.
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for gcc option to accept ISO C99... none needed
checking for gcc option to accept ISO Standard C... (cached) none needed
checking how to run the C preprocessor... gcc -E
checking for a BSD-compatible install... /usr/bin/install -c
checking whether C compiler accepts -std=gnu99... yes
checking whether C compiler accepts -fwrapv... yes
checking for cos in -lm... yes
checking for shutdown in -lsocket... no
checking for PCRE directory... /usr
checking for pcre_free in -lpcre... yes
checking for SSL directory... /usr
checking for CRYPTO_free in -lcrypto... yes
checking for SSL_read in -lssl... yes
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for egrep... /bin/grep -E [295/609]
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking malloc.h usability... yes
checking malloc.h presence... yes
checking for malloc.h... yes
checking sys/resource.h usability... yes
checking sys/resource.h presence... yes
checking for sys/resource.h... yes
checking sys/signal.h usability... yes
checking sys/signal.h presence... yes
checking for sys/signal.h... yes
checking whether time.h and sys/time.h may both be included... yes
checking sys/time.h usability... yes
checking sys/time.h presence... yes
checking for sys/time.h... yes
checking varargs.h usability... no
checking varargs.h presence... no
checking for varargs.h... no
checking stdarg.h usability... yes
checking stdarg.h presence... yes
checking for stdarg.h... yes
checking errno.h usability... yes
checking errno.h presence... yes
checking for errno.h... yes
checking sys/errno.h usability... yes
checking sys/errno.h presence... yes
checking for sys/errno.h... yes
checking for dirent.h that defines DIR... yes
checking for library containing opendir... none required
checking size of long int... 8
checking size of int... 4
checking for pid_t... yes
checking for size_t... yes
checking return type of signal handlers... void
checking whether struct tm is in sys/time.h or time.h... time.h
checking for struct tm.tm_zone... yes
checking for struct tm.tm_gmtoff... yes
checking for mallinfo... yes
checking for getrlimit... yes
checking for getrusage... yes
checking for random... yes
checking for pselect... yes
checking for struct mallinfo.hblks... no
checking for struct mallinfo.keepcost... no
checking for struct mallinfo.treeoverhead... no
checking for struct mallinfo.grain... no
checking for struct mallinfo.allocated... no
checking for struct tm.tm_gmtoff... no
checking whether _timezone is declared... no
checking for an ANSI C-conforming const... yes
checking for long double with more range or precision than double... yes
checking for long long int... yes
checking for long double with more range or precision than double... yes [236/609]
checking for long long int... yes
checking value of uname -a
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating game/restart
config.status: creating include/autoconf.h
You should review the options in include/config.h, and
then type make to build your system.
~/src/fuzzball$ make
for d in src; do \
cd ${d} && make all; \
done
make[1]: Entering directory '/home/jcoffman/src/fuzzball/src'
Creating ../include/defines.h...
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c array.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c boolexp.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c compile.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c create.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c db.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c debugger.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c diskprop.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c edit.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c events.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c fbmath.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c fbsignal.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c fbstrings.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c fbtime.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c game.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c hashtab.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c help.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c interface_ssl.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c interp.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c log.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c look.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c match.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c mcp.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c mcpgui.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c mcppkgs.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c mfuns.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c mfuns2.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c move.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c msgparse.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c mufevent.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_array.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_connects.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_db.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_error.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_float.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_math.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_mcp.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_misc.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_props.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_regex.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_stack.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c p_strings.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c player.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c predicates.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c player.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c predicates.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c propdirs.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c property.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c props.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c rob.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c sanity.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c set.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c sha1.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c speech.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c timequeue.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c tune.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c wiz.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c crt_malloc.c
gcc -g -O2 -std=gnu99 -fwrapv -I../include -I/usr/include -I/usr/include -c interface.c
interface.c: In function ‘configure_new_ssl_ctx’:
interface.c:2060:9: error: ‘ctx’ undeclared (first use in this function)
if (ctx->config->dheparams == -1)
^~~
interface.c:2060:9: note: each undeclared identifier is reported only once for each function it appears in
Makefile:145: recipe for target 'interface.o' failed
make[1]: *** [interface.o] Error 1
make[1]: Leaving directory '/home/jcoffman/src/fuzzball/src'
Makefile:12: recipe for target 'all' failed
make: *** [all] Error 2
Attempting to start the muck while configured with MUD_ID
/MUD_GID
will result in failed start with the following message, if said file does not already exist:
Unable to open logs/status!
(Expected behavior would be to create the file.)
Eventually, Fuzzball should have some form of automated tests that run locally, perhaps a separate make test
step. Ideally, this would include testing normal and SSL connections, running the MUF regression set, and validating that at least basic commands work, if not all commands.
Travis CI and Appveyor could make use of these tests and make sure that new changes don't accidentally break old functionality.
This is a long-term issue, perhaps after the build system is unified, and should involve careful investigation of available testing frameworks (e.g. Google Test), or, if needed, writing one from scratch (e.g. Bitlbee's approach).
I'm not sure if this was an intentional change. In many cases, publicly-usable programs have implementation instructions buried in the MUF body itself, which needs to be @list
ed to see, often by non-MUCKER
users. This also goes directly against the documented functionality of the VIEWABLE
flag, as shown here:
When VEHICLE is set on a program, it is called VIEWABLE, and enables the program to be
@list
ed.
Same with @list
documentation:
Lists lines in a program, provided you control it or it is VIEWABLE.
@version
output from SPR, where this behavior was confirmed:
Version: Muck2.2fb7.00b1(3) Compiled on: Fri Feb 23 2018 at 01:38:34 UTC
Options: GODPRIV IPV6 MCP RESOLVER SSL
When attempting to terminate the MUCK via a systemd unit, shutdown stalls while waiting for the resolver process to exit. Once a kill is sent to the resolver process, everything proceeds to shutdown correctly.
@version:
Version: Muck2.2fb7.00a2(2) Compiled on: Sun Dec 18 2016 at 14:18:39 UTC
Options: DETACH GODPRIV IPV6 MCP RESOLVER SSL
# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.1 LTS
Release: 16.04
Codename: xenial
# uname -a
Linux tassmoj.sprmuck.org 4.4.0-53-generic #74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
# cat /etc/systemd/system/fuzzball-spr.service
[Unit]
Description=Fuzzball MUCK Server (SPR)
After=network.target
[Service]
Type=forking
PIDFile=/opt/fuzzball/spr/game/fbmuck.pid
ExecStart=/opt/fuzzball/spr/restart
Restart=on-failure
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
array_fmtstrings's documentation claims that it defaults to 0 if a value is not an input dictionary, but it doesn't do this for floats or ints or dbrefs. (The code defaults to a null string, which then fails a typecheck.)
The XFORCIBLE
flag is mentioned in the documentation for @set
and @force
, but the documentation for the flag itself seems to have gotten lost at some point. Additionally, I don't think its use on exits/actions (displayed as XPRESS
) was ever documented anywhere.
Examining any room currently reports that room as its own parent. All rooms display this behavior when examined. The following MUF code does correctly report the expected parent:
me @ location location
In a MUF file one can have code outside of any word like:: x ; foreach repeat
. (Not surprisingly, I've found some bugs in how this code is handled.) This code is unreachable but still part of the compiled program instruction list. Probably this should be an error (if we aren't concerned about this kind of backwards-compatibility) or a warning.
Library functions that manipulate the database (especially on behalf of lesser-privileged programs) require the following prologue in order to secure their sysvars from inappropriate actions that the invoker would not be able to perform:
"me" match me ! me @ location loc ! trig trigger !
This prologue takes 8 instructions (push a literal, MATCH, store-to-me, get-from-me, LOCATION, store-to-loc, TRIG, store-to-trigger). This means that library calls can be expensive in terms of instructions used, just to ensure that they are not misused.
SECURE_SYSVARS is a verb to set me @, loc @, and trigger @ to the correct values in one instruction.
array_tree_compare tries to compare floats using a margin of DBL_EPSILON, but this means that its comparison is not transitive. It also uses division by one of the values being compared to scale this comparison, which sometimes divides by zero.
The division by zero definitely needs to get fixed. Any change to array_tree_compare probably changes the user-visible semantics of MUF dictionaries.
When attempting to enable debugging for fbmuck for research on issue #40, we found that we were unable to launch the MUCK with debugging enabled. Same database when compiled without --enable-debug launched without issue.
# cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.1 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.1 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
# uname -a
Linux tassmoj.sprmuck.org 4.4.0-53-generic #74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
@version
Version: Muck2.2fb7.00a2(4) Compiled on: Mon Dec 19 2016 at 01:48:47 UTC
Options: DETACH GODPRIV IPV6 MCP RESOLVER SSL
# cat fbmuck.err
LOADING: /opt/fuzzball/spr/game/data/std-db.db
[debug] dequeue_prog(#171, 1) called from compile.c:1915
dequeue_prog: tqhead = (nil)
[debug] dequeue_prog: 0 instances of #171
[debug] dequeue_prog(#2385, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(3): about to muf_event_dequeue(#2385, 1)
[debug] dequeue_prog: 0 instances of #2385
[debug] dequeue_prog(#7335, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(3): about to muf_event_dequeue(#7335, 1)
[debug] dequeue_prog: 0 instances of #7335
[debug] dequeue_prog(#9009, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(3): about to muf_event_dequeue(#9009, 1)
[debug] dequeue_prog: 0 instances of #9009
[debug] dequeue_prog(#9680, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(3): about to muf_event_dequeue(#9680, 1)
[debug] dequeue_prog: 0 instances of #9680
[debug] dequeue_prog(#11696, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#11696, 1)
[debug] dequeue_prog: 0 instances of #11696
[debug] dequeue_prog(#27249, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#27249, 1)
[debug] dequeue_prog: 0 instances of #27249
[debug] dequeue_prog(#68733, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#68733, 1)
[debug] dequeue_prog: 0 instances of #68733
[debug] dequeue_prog(#73540, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(3): about to muf_event_dequeue(#73540, 1)
[debug] dequeue_prog: 0 instances of #73540
[debug] dequeue_prog(#75066, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#75066, 1)
[debug] dequeue_prog: 0 instances of #75066
[debug] dequeue_prog(#76525, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(3): about to muf_event_dequeue(#76525, 1)
[debug] dequeue_prog: 0 instances of #76525
[debug] dequeue_prog(#79016, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(3): about to muf_event_dequeue(#79016, 1)
[debug] dequeue_prog: 0 instances of #79016
[debug] dequeue_prog(#87549, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(3): about to muf_event_dequeue(#87549, 1)
[debug] dequeue_prog: 0 instances of #87549
[debug] dequeue_prog(#99026, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#99026, 1)
[debug] dequeue_prog: 0 instances of #99026
[debug] dequeue_prog(#116192, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#116192, 1)
[debug] dequeue_prog: 0 instances of #116192
[debug] dequeue_prog(#123836, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#116192, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#123836, 1)
[debug] dequeue_prog: 0 instances of #123836
[debug] dequeue_prog(#145112, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#116192, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#123836, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#145112, 1)
[debug] dequeue_prog: 0 instances of #145112
[debug] dequeue_prog(#164389, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#116192, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#123836, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#145112, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#164389, 1)
[debug] dequeue_prog: 0 instances of #164389
[debug] dequeue_prog(#170646, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#116192, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#123836, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#145112, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#164389, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#170646, 1)
[debug] dequeue_prog: 0 instances of #170646
[debug] dequeue_prog(#173282, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#116192, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#123836, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#145112, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#164389, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#170646, has_refs()=0 ptr->uid=#182194.
dequeue_prog(3): about to muf_event_dequeue(#173282, 1)
[debug] dequeue_prog: 0 instances of #173282
[debug] dequeue_prog(#180634, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133de720
dequeue_prog: tqhead->called_prog = #171, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#2385, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#7335, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#116192, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#123836, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#145112, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#164389, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#170646, has_refs()=0 ptr->uid=#182194.
dequeue_prog(2): ptr->called_prog=#173282, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#180634, 1)
[debug] dequeue_prog: 0 instances of #180634
LOADING: /opt/fuzzball/spr/game/data/std-db.db (done)
Checking objects 0 to 9999...
Checking objects 10000 to 19999...
Checking objects 20000 to 29999...
Checking objects 30000 to 39999...
Checking objects 40000 to 49999...
Checking objects 50000 to 59999...
Checking objects 60000 to 69999...
Checking objects 70000 to 79999...
Checking objects 80000 to 89999...
Checking objects 90000 to 99999...
Checking objects 100000 to 109999...
Checking objects 110000 to 119999...
Checking objects 120000 to 129999...
Checking objects 130000 to 139999...
Checking objects 140000 to 149999...
Checking objects 150000 to 159999...
Checking objects 160000 to 169999...
Checking objects 170000 to 179999...
Checking objects 180000 to 189999...
Checking objects 190000 to 199999...
Checking objects 200000 to 201334...
Searching for orphan objects...
Done.
prog_clean: fr->caller.top=1
Decreasing instances of fr->caller.st[1](#171)
[debug] dequeue_prog(#191413, 1) called from compile.c:1915
dequeue_prog: tqhead = 0x133e80c0
dequeue_prog: tqhead->called_prog = #7335, has_refs = 0 tqhead->uid = #9104
dequeue_prog(2): ptr->called_prog=#9009, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#9680, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#11696, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#27249, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#68733, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#73540, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#75066, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#76525, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#79016, has_refs()=0 ptr->uid=#9104.
dequeue_prog(2): ptr->called_prog=#87549, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#99026, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#116192, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#123836, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#145112, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#164389, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#170646, has_refs()=0 ptr->uid=#182194.
dequeue_prog(2): ptr->called_prog=#173282, has_refs()=0 ptr->uid=#4039.
dequeue_prog(2): ptr->called_prog=#180634, has_refs()=0 ptr->uid=#4039.
dequeue_prog(3): about to muf_event_dequeue(#191413, 1)
[debug] dequeue_prog: 0 instances of #191413
prog_clean: fr->caller.top=1
Decreasing instances of fr->caller.st[1](#7335)
fbmuck: array.c:153: array_tree_find: Assertion `avl != NULL' failed.
PANIC: BAILOUT: caught signal 6
DUMPING: /opt/fuzzball/spr/game/data/std-db.new.PANIC
DUMPING: /opt/fuzzball/spr/game/data/std-db.new.PANIC (done)
The MUF bitwise operators use the same pattern as other arithmetic operations to decide on result types. This means that 0.0 0.0 BITAND
produce a float result. However, the calculation is not done in a way which takes into account that floats are being used (including potentially accessing some out-of-bounds memory when using a pointer to an int containing the result as a pointer to float).
Multiple players have reported that pasting a large block of text causes their connection to drop. After reconnecting, repasting the same text tends to succeed, though in rare cases, several disconnects may occur before the paste attempt succeeds. Most recently, this occurred while I was attempting to paste a 131-line MUF program into the editor.
Currently says:
[ -rot rot ] => [ rot ]
Should be:
[ rot rot ] => [ -rot ]
[ -rot -rot ] => [ rot ]
because:
[ -rot rot ] => [ (nop) ]
Our MUCK is currently managed as a systemd service. Per man systemd.service
, systemd has the capability to restart a service on a non-zero process exit code (Restart=on-failure
), or on ANY process termination (Restart=always
).
Currently, @shutdown
and @restart
both end the process with exit code 0. This leads to an undesirable behavior where both commands either shut the MUCK down or restart it, depending on the service unit configuration.
I propose having a compile time option (include/config.h
most likely) that causes the process to exit with code 0 on @shutdown
and something non-zero (perhaps configurable) on @restart
.
PCRE should be built from source on Windows to keep up with bug-fixes, security improvements, and enable building a 64-bit version of Fuzzball for Windows.
To build from source, Makefile.win
will need to patch the PCRE directory to build it on Windows, then build it as a .dll
, packaging it with the rest of Fuzzball. The Appveyor script will to include pcre.dll
in the published artifact.
For long-term ease of maintenance, two approaches come to mind:
When building on Windows, the instructions will point to downloading the PCRE source code (e.g. from the official site here) and extracting it in the win32
folder. The Appveyor script will need updated to automatically download PCRE.
Fuzzball will provide a Git mirror of the PCRE source code, either uploading the extracted source package, or directly importing using a tool. The main Fuzzball repository can include the PCRE source as a Git submodule.
Both approaches have trade-offs and advantages without a clear winner. More research may be needed to see how other projects approach dependencies.
Other options exist, too - since Conan.io is already used for OpenSSL, a PCRE package could be contributed. Or, though not ideal, a separate repository could contain only PCRE.lib builds, akin to how CyanogenMod handles dependencies.
I pulled this from the email discussion in order to have a single cohesive thread for updates and discussion, keeping it from getting lost.
copyobj's documentation claims that programs can only create one object per run, but this is only true for non-M3+ programs. It also neglects to mention that the copied object is created in the current player's possession rather than copying the original location.
If a program with dbref 3 contains something like:
: main me @ "@edit #3" force me @ "c" force me @ "Done." notify ;
and runs with appropriate permissions, this will crash. It is probably also possible to trigger this via MUF running MPI that FORCE's a user to do a recompile. (I don't think the @edit
command doesn't need to be triggered from MUF, a user who is already editing the program could be FORCE'd.)
As of this date and time, I'm unable to connect to our testing server after pulling the latest code and performing a rebuild. The socket connects, but no welcome message is printed, and if I try to send any text (such as to log in), the connection immediately drops. Nothing out of the ordinary displayed in the logs. Unsecure connections continue to function normally. Let me know what additional data you need.
We're experiencing an issue, albeit infrequently, where the MUCK will completely stop responding to input. Attempting to trace the process yields the following:
# strace -p 22940
strace: Process 22940 attached
futex(0x7f6882b3bac0, FUTEX_WAIT_PRIVATE, 2, NULL
It hangs at this point until strace is interrupted. We've tried launching the MUCK with fbmuck compiled in debug mode, but it fails to read the database when compiled in such fashion. In the mean time, I've pulled down the latest code as of this date/time in the hopes that a committed change has resolved the issue.
All user passwords are currently stored according to the following algorithm:
base64(md5(password))
Using MD5 is, these days, little better than obfuscation, rather than proper security. Combined with a lack of salting, it is trivial to recover user passwords with access to the database.
Salting passwords prior to storage would greatly increase the time to recovery for dictionary and brute-force offline attacks, though with MD5 as the underlying hash, it would still be well within the capability of the average attacker.
Ideally, MD5 would be replaced with a proper key derivation function (bcrypt, PBKDF2, et al.), or at least a multi-round SHA2 digest.
Both of these (salting, algorithm) could be implemented as compile-time options so as not to automatically modify a database in such a way that compatibility is broken with prior versions.
We use the {flag:} function in our obv-exits macro. Previously, this worked fine. Now it's throwing a permissions error. Can I ask what changed?
Updated: Local exit "spoof" and room zero-linked "spoof" were conflicting. For some reason, when the {flags:} function tried to look at the local "spoof" exit by name, it was getting room zero's copy instead, which was causing a permissions failure. Had to set M3 on the local exit to get the precedence to work right. Same behavior noted with "examine." "ex spoof" was giving me the global version, instead of the local one. What caused this change in behavior?
Criteria | Rank | Reason |
---|---|---|
Impact | ★★☆ 2/3 | Not user-facing, but improves developer quality-of-life |
Risk | ★☆☆ 1/3 | Style won't cause issues, automated tools may complicate contributing |
Intrusiveness | ★★★ 3/3 | Will modify almost every single file, not easily reverted |
...I've yet to see enough projects to have a strong view. Quassel uses 4 spaces, Ceph uses both (smarttab
- apparently also controversial), etc.
Discuss in comments?
I pulled this from the email discussion in order to have a single cohesive thread for updates and discussion, keeping it from getting lost.
lsedit me = test
< Welcome to the list editor. You can get help by entering '.h' >
< '.end' will exit and save the list. '.abort' will abort any changes. >
< To save changes to the list, and continue editing, use '.save' >
Program Error. Your program just got the following error.
cmd-lsedit(#107), line 24; CALL: Program not compilable.
System stack backtrace:
0) cmd-lsedit(#107) line 24, in lsedit-loop(:
24: EDITORloop
1) cmd-lsedit(#107) line 89, in cmd-lsedit(:
89: ;
*done*
cmd-lsedit is the version from here. all libs are installed from here.
On SPR, we have the following object:
whengraph.muf(#7335FLAVM3) Owner: SPR
Type: PROGRAM Flags: LINK_OK MUCKER3 VIEWABLE AUTOSTART
A scroll containing a spell called whengraph.muf
Created: Sat Jul 29 13:19:00 UTC 1995
Modified: Sun Apr 23 23:18:47 UTC 2017
Lastused: Sun Apr 23 23:29:00 UTC 2017
Usecount: 9653831 Instances: 0
[ Use 'examine <object>=/' to list root properties. ]
Memory used: 3342 bytes
Program not compiled.
When I attempt to compile/use the program, I receive the following error:
Program not compilable. Cannot run.
The following is recorded in logs/muf-errors
:
2017-04-23T23:46:13: SPR(#9104) [whengraph.muf(#7335)] SPR(#9104) Error in line 2: Number outside procedure.
Nothing was changed aside from pulling the latest (as of this date) code changes and recompiling on our sandbox system.
Output of @list #7335=1-10
:
(WhenGraph - Another W* Program by Riss! 6/6/95)
PREEMPT
var CC
var scale
var dif
: dohelp
"WhenGraph - By Riss - Ver 1.2" .tell
" WG - Displays a graph of the last 24 hours low and" .tell
" counts of connections to the server. " .tell
" WG #dif - Same display but with differential graph." .tell
10 lines displayed.
Is there an issue with the PREEMPT
primitive that's generating this error? Is PREEMPT
now required to be used within a MUF word rather than outside?
Just out of curiosity (no rush as the changes aren't urgent):
I noticed in the fuzzball repository, there's this directory:
dbs/advancedb/muf
It has the same stuff (pretty much) that the fuzzball-muf repository has. When/how do changes move from fuzzball-muf to fuzzball itself?
I'm mostly used to mailing lists, so I apologise in advance for being so goofy with github. I don't know how else to contact you guys! Thanks for reading my question!
The lock parsing/evaluation/unparsing code is recursive and the only limits on the number of levels are based on what can be fit in a (~8KB) lock string. It might be wise to have some explicit depth limit rather than have a way that users might be able to make the MUCK run out of stack space.
The docs for array_get_proplist say it returns a dictionary keyed by propname, but the implementation returns a list-type array.
The MUF primitive TAN's documentation says it only operates within -pi/4 to pi/4.
In fact, TAN checks whether its input is K*pi + pi/2 (for some K) and indicates NaN by returning zero and setting err_isnan? in this case. For other values (except inf/nan), it uses the system tan function.
@tune
settings are persisted to disk regardless of validity
@restart
/crashing could result in server not being available@reconfigure_ssl
can apply valid settings that lock out wizards
TLSv1.2
(higher is more secure, right?) when using TLSv1.1 client@reconfigure_ssl
/@tune
does not allow reverting to "last known working" settingsCriteria | Rank | Reason |
---|---|---|
Impact | ★★☆ 2/3 | Resolves server lock-out that requires wizard access to cause |
Risk | ★★☆ 2/3 | Possible subtle errors, but testing should catch most |
Intrusiveness | ★★☆ 2/3 | May require settings overhaul, SSL refactoring |
No firm implementations have been decided on yet.
In general, this requires some way of storing a last-known good configuration and requiring confirmation before persisting.
@restart
Other options..?
There's other options, and almost certainly other trade-offs I haven't considered. I'm not sure of what's the best approach.
I pulled this from the email discussion in order to have a single cohesive thread for updates and discussion, keeping it from getting lost. Thanks to Wyld, Kyle, and Keet for your comments!
User passwords are displayed in cleartext in the command log when using @password
or @newpassword
. These should be masked or omitted from the command log.
Opened from e-mail delivered to me:
From: Obscenity Furr (email redacted)
I've tried both fbmuck 6 and 7 and both cant do anything but print the help screen, trying to run a server just flashes another console, I've tried adding '-freeconsole' but the console still flashes, this time creating 0 byte log files.
The systems I've had the same issue on are Ubuntu Server 16.10 and Windows 10. I've also tried compiling it myself, same issue.
Can you help me out?
Nested arrays and array_pin can leak memory. For example, the MUF program:
: main { }dict ARRAY_PIN DUP 0 ARRAY_SETITEM DUP DUP ARRAY_SETITEM ;
leaks memory (AddressSanitizer report):
=================================================================
==7216==ERROR: LeakSanitizer: detected memory leaks
Indirect leak of 56 byte(s) in 1 object(s) allocated from:
#0 0x4d0730 in calloc (/home/charles/software/fbmuck-code2/src/fbmuck+0x4d0730)
#1 0x50ca16 in array_tree_alloc_node /home/charles/software/fbmuck-code2/src/array.c:303:31
#2 0x50ca16 in array_tree_insert /home/charles/software/fbmuck-code2/src/array.c:355
#3 0x50a9e4 in array_setitem /home/charles/software/fbmuck-code2/src/array.c:931:7
#4 0x5d287c in prim_array_setitem /home/charles/software/fbmuck-code2/src/p_array.c:338:14
#5 0x57b4c2 in interp_loop /home/charles/software/fbmuck-code2/src/interp.c:1726:3
#6 0x5bd24a in do_move /home/charles/software/fbmuck-code2/src/move.c:485:6
#7 0x568b68 in process_command /home/charles/software/fbmuck-code2/src/game.c
#8 0x6e3d17 in do_command /home/charles/software/fbmuck-code2/src/interface.c:1000:6
#9 0x6e3d17 in process_commands /home/charles/software/fbmuck-code2/src/interface.c:1071
#10 0x6e3d17 in shovechars /home/charles/software/fbmuck-code2/src/interface.c:2324
#11 0x6e1991 in main /home/charles/software/fbmuck-code2/src/interface.c:4532:2
#12 0x7f8d7e11b3f0 in __libc_start_main /build/glibc-mXZSwJ/glibc-2.24/csu/../csu/libc-start.c:291
Indirect leak of 24 byte(s) in 1 object(s) allocated from:
#0 0x4d0538 in malloc (/home/charles/software/fbmuck-code2/src/fbmuck+0x4d0538)
#1 0x509971 in new_array /home/charles/software/fbmuck-code2/src/array.c:526:24
#2 0x509971 in new_array_dictionary /home/charles/software/fbmuck-code2/src/array.c:574
#3 0x5ceff9 in prim_array_make_dict /home/charles/software/fbmuck-code2/src/p_array.c:75:10
#4 0x57b4c2 in interp_loop /home/charles/software/fbmuck-code2/src/interp.c:1726:3
#5 0x5bd24a in do_move /home/charles/software/fbmuck-code2/src/move.c:485:6
#6 0x568b68 in process_command /home/charles/software/fbmuck-code2/src/game.c
#7 0x6e3d17 in do_command /home/charles/software/fbmuck-code2/src/interface.c:1000:6
#8 0x6e3d17 in process_commands /home/charles/software/fbmuck-code2/src/interface.c:1071
#9 0x6e3d17 in shovechars /home/charles/software/fbmuck-code2/src/interface.c:2324
#10 0x6e1991 in main /home/charles/software/fbmuck-code2/src/interface.c:4532:2
#11 0x7f8d7e11b3f0 in __libc_start_main /build/glibc-mXZSwJ/glibc-2.24/csu/../csu/libc-start.c:291
SUMMARY: AddressSanitizer: 80 byte(s) leaked in 2 allocation(s).
The MUF program
: main
{ 1 2 3 }list ARRAY_PIN var! x
{ 4 5 6 }list ARRAY_PIN var! y
x @ y @ 0 ARRAY_SETITEM POP
y @ x @ 0 ARRAY_SETITEM POP
x @ y @ ARRAY_COMPARE
;
causes the server to overflow its stack.
The built-in command @sweep
is intended to identify say traps on the environment, but it assumes that say traps will be linked to a MUF program. Therefore, it won't detect some secnario like:
@create ThingWithSayTrap
@act say=ThingWithSayTrap
@lock say=me&!me
@link say=here
@fail say={null:some MPI that does something with {&arg}}
drop ThingWithSayTrap
@sweep
Here are some memory leaks and buffer over/underflows from fuzz testing:
@tune oTest=here
leaks at tune.c:810 (strdup into oldvalue)@act toTest=here
, then @lock toTest=#3&
performs an out-of-bounds stack read (underflow) at boolexp.c:193 (parse_boolexp_F)@find o[^x]
on a database containing an object named "Two" performs an out-of-bounds access in smatch
when performing smatch
for o
and o[^x]*
@act toTest=here
then @fail toTest={&propdirs-example:r}
then toTest
will perform an out-of-bounds write to cmdbuf at msgparse.c line 770.@act toTest=here
then @fail toTest={le:rgo,\
then toTest
will leak from the malloc at msgparse line 686 (for argv[argv]).{list:,me}
performs an out-of-bounds access at msgparse.c:250 (listname[len-1]); there appears to be a similar problem with {select:...} at msgparse.c:190{NULL:{WHILE:1,{NULL:x}{NULL}{NULL:{NULL:{NULL}}}}}}}}}}}}}}
leaks from msgparse.c line 903 (argv[i] = (char *) realloc(....
in the mfun_list[s].parsep
case){filter:b,a,{in`valid}}}}}
leaks from msgparse.c:686: main FOR IF BREAK
leaks (when compiled) from add_loop_exit() around compile.c:3134"" NEWPROGRAM
performs a null pointer dereferenceNEXTENTRANCE
doesn't check for stack underflow"" 0.0 0.0 0.0 DIFF3
when run on an empty stack triggers an assertion failure on a MUCK built with --enable-debug: x 0 forcedby_array array_notify_secure ;
causes an assertion failure on a MUCK built with --enable-debug: main pop "" 0 over main and and ;
causes an assertion failure on a MUCK built with --enable-debugIn my ongoing attempt to improve the security posture of MUCK servers and their clients, I'm trying to collect data on what TLS mode is being negotiated with each client as it connects in order to determine what clients will be affected by security configuration changes, such as the one motivated by the ROBOT attack.
That information is currently only presented to the client, and only for those clients lucky enough to use software that even bothers to report that data. Can we add data to the status log that indicates what cipher suite is used when a connection is established?
Reported to me by Puck of HLM:
The OS X build environment does not include pcre by default. FB's configure script has an option for --without-pcre which it accepts. However the actual make still fails with 'pcre.h not found' so either it needs to be specified that pcre is required (it can be added to OS X, it's just not there by default) or the configure/make stuff needs to be fixed to be able to correctly build without pcre.
If you do @set me=%x:%Nx
then run the MPI {pronouns:foo%xfoo,me}
, the result is fooMyNameXoo
instead of fooMyNamexfoo
or fooMyNameXfoo
.
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.