summaryrefslogtreecommitdiff
path: root/src/sp_sloppy.c
blob: 5b36026c374097469610911eb85516a5b3443cd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "php_snuffleupagus.h"
#include "sp_sloppy.h"

ZEND_DECLARE_MODULE_GLOBALS(snuffleupagus)

ZEND_API zend_op_array* (*orig_zend_compile_file)(zend_file_handle* file_handle,
                                                  int type) = NULL;
ZEND_API zend_op_array* (*orig_zend_compile_string)(zval* source_string,
                                                    char* filename) = NULL;

static void modify_opcode(zend_op_array* opline) {
  if (NULL != opline) {
    for (size_t i = 0; i < opline->last; i++) {
      zend_op* orig_opline = &(opline->opcodes[i]);
      if (orig_opline->opcode == ZEND_IS_EQUAL) {
        orig_opline->opcode = ZEND_IS_IDENTICAL;
        zend_vm_set_opcode_handler(orig_opline);
      } else if (orig_opline->opcode == ZEND_IS_NOT_EQUAL) {
        orig_opline->opcode = ZEND_IS_NOT_IDENTICAL;
        zend_vm_set_opcode_handler(orig_opline);
      }
    }
  }
}

ZEND_API zend_op_array* sp_compile_string(zval* source_string, char* filename) {
  zend_op_array* opline = orig_zend_compile_string(source_string, filename);
  modify_opcode(opline);
  return opline;
}

ZEND_API zend_op_array* sp_compile_file(zend_file_handle* file_handle,
                                        int type) {
  zend_op_array* opline = orig_zend_compile_file(file_handle, type);
  modify_opcode(opline);
  return opline;
}

static void array_handler(INTERNAL_FUNCTION_PARAMETERS,
    const char *name, size_t size,
    void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS)) {
  void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
  zval func_name;
  zval params[3];
  zval *value, *array;
  zend_bool strict;

  memset(&params, 0, sizeof(params));
  zend_parse_parameters(ZEND_NUM_ARGS(), "zz|b", &value, &array, &strict);

  ZVAL_COPY(&params[0], value);
  ZVAL_COPY(&params[1], array);
  ZVAL_BOOL(&params[2], 1);
  ZVAL_STRING(&func_name, name);

  handler = zend_hash_str_find_ptr(
      SNUFFLEUPAGUS_G(sp_internal_functions_hook), name, size);
  zend_internal_function *func = zend_hash_str_find_ptr(
      CG(function_table), name, size);
  func->handler = handler;

  call_user_function(CG(function_table), NULL, &func_name,
      return_value, 3, params);

  func->handler = orig_handler;
}

PHP_FUNCTION(sp_in_array) {
  array_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, "in_array",
      sizeof("in_array") - 1, PHP_FN(sp_in_array));
}

PHP_FUNCTION(sp_array_search) {
  array_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, "array_search",
      sizeof("array_search") - 1, PHP_FN(sp_array_search));
}

PHP_FUNCTION(sp_array_keys) {
  array_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, "array_keys",
      sizeof("array_keys") - 1, PHP_FN(sp_array_keys));
}

void hook_sloppy() {
  TSRMLS_FETCH();

  if (NULL == orig_zend_compile_file) {
    orig_zend_compile_file = zend_compile_file;
    zend_compile_file = sp_compile_file;
  }

  if (NULL == orig_zend_compile_string) {
    orig_zend_compile_string = zend_compile_string;
    zend_compile_string = sp_compile_string;
  }

  HOOK_FUNCTION("in_array", sp_internal_functions_hook, PHP_FN(sp_in_array));
  HOOK_FUNCTION("array_search", sp_internal_functions_hook, PHP_FN(sp_array_search));
  HOOK_FUNCTION("array_keys", sp_internal_functions_hook, PHP_FN(sp_array_keys));
}