cgen: obfuscate functions

pull/8511/head
Alexander Medvednikov 2021-02-02 09:14:34 +01:00
parent 5ec6f7a781
commit 2c4674eb42
5 changed files with 81 additions and 4 deletions

View File

@ -165,7 +165,7 @@ fn (foptions &FormatOptions) format_file(file string) {
parent: 0
})
// checker.check(file_ast)
formatted_content := fmt.fmt(file_ast, table, foptions.is_debug)
formatted_content := fmt.fmt(file_ast, table, prefs, foptions.is_debug)
file_name := os.file_name(file)
ulid := rand.ulid()
vfmt_output_path := os.join_path(vtmp_folder, 'vfmt_${ulid}_$file_name')
@ -189,7 +189,7 @@ fn (foptions &FormatOptions) format_pipe() {
parent: 0
})
// checker.check(file_ast)
formatted_content := fmt.fmt(file_ast, table, foptions.is_debug)
formatted_content := fmt.fmt(file_ast, table, prefs, foptions.is_debug)
print(formatted_content)
if foptions.is_verbose {
eprintln('fmt.fmt worked and $formatted_content.len bytes were written to stdout.')

View File

@ -7,6 +7,7 @@ import v.ast
import v.table
import strings
import v.util
import v.pref
const (
bs = '\\'
@ -46,9 +47,10 @@ pub mut:
inside_lambda bool
inside_const bool
is_mbranch_expr bool // math a { x...y { } }
pref &pref.Preferences
}
pub fn fmt(file ast.File, table &table.Table, is_debug bool) string {
pub fn fmt(file ast.File, table &table.Table, pref &pref.Preferences, is_debug bool) string {
mut f := Fmt{
out: strings.new_builder(1000)
out_imports: strings.new_builder(200)
@ -56,6 +58,7 @@ pub fn fmt(file ast.File, table &table.Table, is_debug bool) string {
indent: 0
file: file
is_debug: is_debug
pref: pref
}
f.process_file_imports(file)
f.set_current_module_name('main')
@ -323,7 +326,7 @@ pub fn (mut f Fmt) stmts(stmts []ast.Stmt) {
mut prev_stmt := if stmts.len > 0 { stmts[0] } else { ast.Stmt{} }
f.indent++
for stmt in stmts {
if f.should_insert_newline_before_stmt(stmt, prev_stmt) {
if !f.pref.building_v && f.should_insert_newline_before_stmt(stmt, prev_stmt) {
f.out.writeln('')
}
f.stmt(stmt)

View File

@ -148,6 +148,7 @@ mut:
timers &util.Timers = util.new_timers(false)
force_main_console bool // true when [console] used on fn main()
as_cast_type_names map[string]string // table for type name lookup in runtime (for __as_cast)
obf_table map[string]string
}
pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string {
@ -427,6 +428,29 @@ pub fn (mut g Gen) init() {
if g.pref.is_livemain || g.pref.is_liveshared {
g.generate_hotcode_reloading_declarations()
}
// Obfuscate only functions in the main module for now.
// Generate the obf_table.
if g.pref.obfuscate {
mut i := 0
// fns
for key, f in g.table.fns {
if f.mod != 'main' && key != 'main' { // !key.starts_with('main.') {
continue
}
g.obf_table[key] = '_f$i'
i++
}
// methods
for type_sym in g.table.types {
if type_sym.mod != 'main' {
continue
}
for method in type_sym.methods {
g.obf_table[type_sym.name + '.' + method.name] = '_f$i'
i++
}
}
}
}
pub fn (mut g Gen) finish() {
@ -3816,6 +3840,14 @@ fn (mut g Gen) ident(node ast.Ident) {
}
}
}
} else if node_info is ast.IdentFn {
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') {
key := node.name
g.write('/* obf identfn: $key */')
name = g.obf_table[key] or {
panic('cgen: obf name "$key" not found, this should never happen')
}
}
}
g.write(g.get_ternary_name(name))
}
@ -5688,6 +5720,17 @@ fn (mut g Gen) go_stmt(node ast.GoStmt, joinable bool) string {
name = fsym.name
}
name = util.no_dots(name)
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') {
mut key := expr.name
if expr.is_method {
sym := g.table.get_type_symbol(expr.receiver_type)
key = sym.name + '.' + expr.name
}
g.write('/* obf go: $key */')
name = g.obf_table[key] or {
panic('cgen: obf name "$key" not found, this should never happen')
}
}
g.writeln('// go')
wrapper_struct_name := 'thread_arg_' + name
wrapper_fn_name := name + '_thread_wrapper'

View File

@ -78,6 +78,18 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
name += '_' + gen_name
}
}
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__')
&& name != 'main__main'&& node.name != 'str' {
mut key := node.name
if node.is_method {
sym := g.table.get_type_symbol(node.receiver.typ)
key = sym.name + '.' + node.name
}
g.writeln('/* obf: $key */')
name = g.obf_table[key] or {
panic('cgen: fn_decl: obf name "$key" not found, this should never happen')
}
}
// if g.pref.show_cc && it.is_builtin {
// println(name)
// }
@ -457,6 +469,16 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
name = 'map_keys_1'
}
}
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__')
&& node.name != 'str' {
sym := g.table.get_type_symbol(node.receiver_type)
// key = g.cc_type2(node.receiver.typ) + '.' + node.name
key := sym.name + '.' + node.name
g.write('/* obf method call: $key */')
name = g.obf_table[key] or {
panic('cgen: obf name "$key" not found, this should never happen')
}
}
// Check if expression is: arr[a..b].clone(), arr[a..].clone()
// if so, then instead of calling array_clone(&array_slice(...))
// call array_clone_static(array_slice(...))
@ -620,6 +642,14 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
} else {
name = c_name(name)
}
// Obfuscate only functions in the main module for now
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') {
key := node.name
g.write('/* obf call: $key */')
name = g.obf_table[key] or {
panic('cgen: obf name "$key" not found, this should never happen')
}
}
for i, generic_type in node.generic_types {
// Using _T_ to differentiate between get<string> and get_string
// `foo<int>()` => `foo_T_int()`

View File

@ -47,6 +47,7 @@ const (
'cflags', 'path']
)
[ref_only]
pub struct Preferences {
pub mut:
os OS // the OS to compile for