Skip to content

Instantly share code, notes, and snippets.

@jhass jhass/injecting_io.cr
Last active Mar 30, 2017

Embed
What would you like to do?
Crystal injecting/replacing IO PoC
struct Slice(T)
def []?(start, count)
if start + count >= size
count = -1
end
if count < 0
count = size - start + (count + 1)
end
self[start, count]
end
end
class InjectingIO
include IO
getter? closed = false
@remaining_token : Bytes?
def initialize(@io : IO, @token : Bytes, @replacement : Bytes)
end
def read(slice : Bytes)
check_open
@io.read(slice)
end
def write(slice : Bytes)
check_open
remaining_token = @remaining_token
if remaining_token
if slice[0, remaining_token.size]? == remaining_token
@io.write(@replacement)
@io.write(slice[remaining_token.size, -1]?)
@remaining_token = nil
return
elsif slice.size < remaining_token.size
if slice == remaining_token[0, slice.size]?
@remaining_token = remaining_token[slice.size, -1]?
return
else
@io.write(@token[0, @token.size - remaining_token.size])
@remaining_token = nil
end
else
@io.write(@token[0, @token.size - remaining_token.size])
@remaining_token = nil
end
end
first_half = slice
second_half = nil
slice.each_index do |i|
candidate = slice[i, @token.size]?
if candidate == @token
first_half = slice[0, i]?
second_half = slice[i + @token.size, -1]?
break
elsif candidate.size < @token.size && candidate == @token[0, candidate.size]?
@remaining_token = @token[candidate.size, -1]?
first_half = slice[0, i]?
break
end
end
@io.write(first_half)
if second_half
@io.write(@replacement)
@io.write(second_half)
end
end
def close
@io.close
@closed = true
end
end
io = InjectingIO.new(STDOUT, "foo".to_slice, "bar".to_slice)
io.puts "Hello World"
io.puts "Hello foo"
io.print "fo"
io.puts "o is cool"
io.print "f"
io.puts "oo is cooler"
io.print "f"
io.print "o"
io.puts "o is the coolest"
io.print "foo"
io.puts " is okay too"
io.print "fo"
io.puts " stays"
io.close
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.