~aleteoryx/tclircc

5363eb2f1e00b84914e479c9b330d66449a3dcaf — aleteoryx a month ago 1c9eee3
various things, i found a uaf in the core distro
5 files changed, 42 insertions(+), 42 deletions(-)

M db/main.tcl
M irc/main.tcl
M main.tcl
M plugins.tcl
M threads.tcl
M db/main.tcl => db/main.tcl +4 -4
@@ 5,13 5,13 @@ set log [logger::init tclircc::db]

switch -- [set tcl_platform(platform)] {
  "windows" {
    set data_dir "[set env(APPDATA)][file separator]tclircc"
    set data_dir [file join [set env(APPDATA)] tclircc]
  }
  "unix" {
    if [info exists env(XDG_CONFIG_HOME)] {
      set data_dir "[set env(XDG_CONFIG_HOME)][file separator]tclircc"
      set data_dir [file join [set env(XDG_CONFIG_HOME)] tclircc]
    } elseif [info exists env(HOME)] {
      set data_dir "[set env(HOME)][file separator].config[file separator]tclircc"
      set data_dir [file join [set env(HOME)] .config tclircc]
    } else {
      return -code error {Missing $HOME or $XDG_CONFIG_HOME, can't store config!}
    }


@@ 25,5 25,5 @@ file mkdir $data_dir

proc path_to_core {} {
  global data_dir
  return "$data_dir[file separator]core.db"
  return [file join $data_dir core.db]
}

M irc/main.tcl => irc/main.tcl +2 -2
@@ 1,5 1,5 @@
package require logger

source "$path[file separator]irc.tcl"
source "$path[file separator]cap.tcl"
source [file join $path irc.tcl]
source [file join $path cap.tcl]


M main.tcl => main.tcl +8 -4
@@ 4,6 4,7 @@ set path [file dirname [dict get [info frame 0] file]]
set version v0.0.1

package require Thread
thread::id; # avoid use-after-free
package require logger
set log [logger::init tclircc::main]
package require sqlite3


@@ 13,6 14,11 @@ ${log}::info "running from $path"

source threads.tcl

proc on_threads_update {} {
  puts "threads updated!"
  t::debug
}

proc start_thread {name} {
  global path
  global version


@@ 24,7 30,7 @@ proc start_thread {name} {
  threads::manage $thread tclircc::$name
  thread::send $thread [list variable path $path version $version]

  if {[thread::send $thread [list source "$path[file separator]$name[file separator]main.tcl"] result] == 1} {
  if {[thread::send $thread [list source [file join $path $name main.tcl]] result] == 1} {
    ${log}::critical "couldn't start $name thread: $result"
    exit -1
  }


@@ 43,13 49,11 @@ source plugins.tcl
start_thread irc
start_thread ui

plugins::load "$path[file separator]testplugin"
plugins::load [file join $path testplugin]

${log}::debug "opening initial window..."
thread::send [t::ns tclircc::ui] {mk_toplevel name; return $name} initial
${log}::debug "initial window opened: $initial"

threads::debug

${log}::info "entering event loop"
vwait nil

M plugins.tcl => plugins.tcl +3 -1
@@ 24,12 24,14 @@ namespace eval plugins {
  variable plugins
  variable log [logger::init tclircc::plugins]

  proc enroll_interp {tid iid} {}

  proc load {dir} {
    variable log

    ${log}::info "attempting to load plugin from \"$dir\"..."

    set mf_path "$dir[file separator]manifest.tcl"
    set mf_path [file join $dir manifest.tcl]
    if {!([file isfile $mf_path] && [file readable $mf_path])} {
      ${log}::error "couldn't load plugin: manifest \"$mf_path\" not present or not readable!"
      return 0

M threads.tcl => threads.tcl +25 -31
@@ 2,25 2,33 @@ namespace eval threads {
  variable threads [list main [thread::id]]
  variable log [logger::init tclircc::threads]

  variable t_ns_script {
    namespace eval ::t {
      variable ns
      proc update {} {
        variable ns
        thread::send -head [set ns(main)] threads::update
      }
      proc ns {name} {
        variable ns
        set ns($name)
      }
      proc debug {} {
        variable log
        parray t::ns
      }
    }
  }
  eval $t_ns_script

  proc manage {tid name} {
    variable threads
    variable log
    variable t_ns_script
    dict set threads $name $tid
    ${log}::debug "managing thread $tid as \"$name\""

    thread::send -head $tid {
      namespace eval t {
        variable ns
        proc update {} {
          variable ns
          thread::send -head [set ns(main)] threads::update
        }
        proc ns {name} {
          variable ns
          set ns($name)
        }
      }
    }
    thread::send -head $tid $t_ns_script

    ::threads::update
  }


@@ 41,26 49,12 @@ namespace eval threads {
      dict for {n t} $threads {
        append payload {set t::ns(} $n {) } $t {; }
      }
      append payload {
        if {"on_threads_update" in [info procs on_threads_update]} \
          on_threads_update
      }
      thread::send -head $tid $payload
    }
    ::update
  }
  proc debug {} {
    variable log
    update
    foreach key [array names threads::ns] {
      ${log}::debug "thread \"$key\" has id [set threads::ns($key)]"
    }
  }
}
namespace eval t {
  variable ns
  proc update {} {
    variable ns
    thread::send -head [set ns(main)] threads::update
  }
  proc ns {name} {
    variable ns
    set ns($name)
  }
}