Skip to content

Commit c5c5e16

Browse files
committed
Initial Upload
0 parents  commit c5c5e16

File tree

10 files changed

+386
-0
lines changed

10 files changed

+386
-0
lines changed

.gitignore

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Files
2+
3+
.DS_Store
4+
5+
# Directories
6+
7+
/private
8+
9+
# PHP Extension
10+
11+
*.dep
12+
*.lo
13+
*.la
14+
.libs
15+
acinclude.m4
16+
aclocal.m4
17+
autom4te.cache
18+
build
19+
config.cache
20+
config.guess
21+
config.h
22+
config.h.in
23+
config.log
24+
config.nice
25+
config.nice.bat
26+
config.status
27+
config.sub
28+
configure
29+
configure.ac
30+
configure.bat
31+
configure.in
32+
configure.js
33+
include
34+
install-sh
35+
libtool
36+
ltmain.sh
37+
Makefile
38+
Makefile.fragments
39+
Makefile.global
40+
Makefile.objects
41+
missing
42+
mkinstalldirs
43+
modules
44+
php_test_results_*.txt
45+
phpt.*
46+
run-test-info.php
47+
run-tests.php
48+
tests/**/*.diff
49+
tests/**/*.out
50+
tests/**/*.php
51+
tests/**/*.exp
52+
tests/**/*.log
53+
tests/**/*.sh
54+
tests/**/*.db
55+
tests/**/*.mem
56+
tmp-php.ini
57+
*~

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## PHP Extension — NOP
2+
3+
Sometimes you just want to disable the functionality of a build-in PHP function without touching code or using the `disable_functions` option which spits out a fatal error.
4+
This extension is a proof of concept that allows you to replace any built-in function in PHP with a NOP (no operation) function.
5+
The NOP replacement function does not return any value so it is not guaranteed to be a drop-in replacement for all functions.
6+
7+
## Installation
8+
9+
Once you copy the `.so` file to the PHP extensions directory, you can enable it by adding the following line to your `php.ini` file:
10+
11+
```ini
12+
extension=nop.so
13+
nop.ignore_functions=chmod,chown
14+
```
15+
16+
Notice that `nop.ignore_functions` is a comma-separated list of functions that you want to replace with the NOP function.
17+
18+
## Development
19+
20+
```
21+
# Run inside docker container
22+
docker run -v `pwd`:/usr/src -w /usr/src --rm -it php:8.3-cli-alpine sh
23+
24+
# Install build dependencies and build the extension
25+
apk --update add php83-dev make g++
26+
phpize && ./configure && make && make install
27+
28+
# Setup a quick test
29+
touch ./private/sample
30+
echo "<?php chmod(__DIR__ . '/sample', 0777);" > ./private/sample.php
31+
32+
# Run the test
33+
chmod 644 ./private/sample
34+
ls -la ./private/sample
35+
php -d 'extension=nop.so' -d 'nop.ignore_functions=chmod' ./private/sample.php
36+
ls -la ./private/sample
37+
```
38+
39+
## Additional Resources
40+
41+
- https://www.phpinternalsbook.com/
42+
- https://www.zend.com/sites/zend/files/pdfs/whitepaper-zend-php-extensions.pdf

config.m4

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
dnl Autotools config.m4 for PHP extension nop
2+
3+
dnl Comments in this file start with the string 'dnl' (discard to next line).
4+
dnl Remove where necessary.
5+
6+
dnl If extension references and depends on an external library package, use
7+
dnl the '--with-nop' configure option:
8+
dnl PHP_ARG_WITH([nop],
9+
dnl [for nop support],
10+
dnl [AS_HELP_STRING([--with-nop],
11+
dnl [Include nop support])])
12+
13+
dnl Otherwise use the '--enable-nop' configure option:
14+
PHP_ARG_ENABLE([nop],
15+
[whether to enable nop support],
16+
[AS_HELP_STRING([--enable-nop],
17+
[Enable nop support])],
18+
[no])
19+
20+
AS_VAR_IF([PHP_NOP], [no],, [
21+
dnl This section is executed when extension is enabled with one of the above
22+
dnl configure options. Adjust and add tests here.
23+
24+
dnl
25+
dnl Use and adjust this code block if extension depends on external library
26+
dnl package which supports pkg-config.
27+
dnl
28+
dnl Find library package with pkg-config.
29+
dnl PKG_CHECK_MODULES([LIBFOO], [foo])
30+
dnl
31+
dnl Or if you need to check for a particular library version with pkg-config,
32+
dnl you can use comparison operators. For example:
33+
dnl PKG_CHECK_MODULES([LIBFOO], [foo >= 1.2.3])
34+
dnl PKG_CHECK_MODULES([LIBFOO], [foo < 3.4])
35+
dnl PKG_CHECK_MODULES([LIBFOO], [foo = 1.2.3])
36+
dnl
37+
dnl Add library compilation and linker flags to extension.
38+
dnl PHP_EVAL_INCLINE([$LIBFOO_CFLAGS])
39+
dnl PHP_EVAL_LIBLINE([$LIBFOO_LIBS], [NOP_SHARED_LIBADD])
40+
dnl
41+
dnl Check for library and symbol presence.
42+
dnl LIBNAME=nop # you may want to change this
43+
dnl LIBSYMBOL=nop # you most likely want to change this
44+
dnl
45+
dnl If you need to check for a particular library function (e.g. a conditional
46+
dnl or version-dependent feature) and you are using pkg-config:
47+
dnl PHP_CHECK_LIBRARY([$LIBNAME], [$LIBSYMBOL],
48+
dnl [AC_DEFINE([HAVE_NOP_FEATURE], [1],
49+
dnl [Define to 1 if nop has the 'FEATURE'.])],
50+
dnl [AC_MSG_FAILURE([FEATURE not supported by your nop library.])],
51+
dnl [$LIBFOO_LIBS])
52+
dnl
53+
54+
dnl
55+
dnl Or use and adjust this code block if extension depends on external library
56+
dnl package, which does not support pkg-config.
57+
dnl
58+
dnl Path to library package can be given as parameter (--with-nop=<DIR>)
59+
dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
60+
dnl SEARCH_FOR="/include/nop.h" # you most likely want to change this
61+
dnl AS_IF([test -r $PHP_NOP/$SEARCH_FOR],
62+
dnl [NOP_DIR=$PHP_NOP],
63+
dnl [
64+
dnl for i in $SEARCH_PATH; do
65+
dnl AS_IF([test -r $i/$SEARCH_FOR],
66+
dnl [NOP_DIR=$i; break;])
67+
dnl done
68+
dnl ])
69+
dnl
70+
dnl AC_MSG_CHECKING([for nop library package])
71+
dnl AS_VAR_IF([NOP_DIR],, [
72+
dnl AC_MSG_RESULT([not found])
73+
dnl AC_MSG_ERROR([Please reinstall the nop library package])
74+
dnl ], [AC_MSG_RESULT([found in $NOP_DIR])])
75+
dnl
76+
dnl Add include flag where library package headers are located on the system.
77+
dnl PHP_ADD_INCLUDE([$NOP_DIR/include])
78+
dnl
79+
dnl Check for library and symbol presence.
80+
dnl LIBNAME=nop # you may want to change this
81+
dnl LIBSYMBOL=nop # you most likely want to change this
82+
dnl
83+
dnl If you need to check for a particular library function (e.g. a conditional
84+
dnl or version-dependent feature) and you are not using pkg-config:
85+
dnl PHP_CHECK_LIBRARY([$LIBNAME], [$LIBSYMBOL], [
86+
dnl PHP_ADD_LIBRARY_WITH_PATH([$LIBNAME],
87+
dnl [$NOP_DIR/$PHP_LIBDIR],
88+
dnl [NOP_SHARED_LIBADD])
89+
dnl AC_DEFINE([HAVE_NOP_FEATURE], [1],
90+
dnl [Define to 1 if nop has the 'FEATURE'.])
91+
dnl ],
92+
dnl [AC_MSG_FAILURE([FEATURE not supported by your nop library.])],
93+
dnl [-L$NOP_DIR/$PHP_LIBDIR -lm])
94+
dnl
95+
96+
dnl Add linked libraries flags for shared extension to the generated Makefile.
97+
dnl PHP_SUBST([NOP_SHARED_LIBADD])
98+
99+
dnl Define a preprocessor macro to indicate that this PHP extension can
100+
dnl be dynamically loaded as a shared module or is statically built into PHP.
101+
AC_DEFINE([HAVE_NOP], [1],
102+
[Define to 1 if the PHP extension 'nop' is available.])
103+
104+
dnl Configure extension sources and compilation flags.
105+
PHP_NEW_EXTENSION([nop],
106+
[nop.c],
107+
[$ext_shared],,
108+
[-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
109+
])

config.w32

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
ARG_ENABLE('nop', 'nop support', 'no');
2+
3+
if (PHP_NOP != 'no') {
4+
AC_DEFINE('HAVE_NOP', 1, "Define to 1 if the PHP extension 'nop' is available.");
5+
6+
EXTENSION('nop', 'nop.c', null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
7+
}

nop.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/* nop extension for PHP */
2+
3+
#ifdef HAVE_CONFIG_H
4+
# include <config.h>
5+
#endif
6+
7+
#include "php.h"
8+
#include "ext/standard/info.h"
9+
#include "php_nop.h"
10+
#include "nop_arginfo.h"
11+
12+
/* For compatibility with older PHP versions */
13+
#ifndef ZEND_PARSE_PARAMETERS_NONE
14+
#define ZEND_PARSE_PARAMETERS_NONE() \
15+
ZEND_PARSE_PARAMETERS_START(0, 0) \
16+
ZEND_PARSE_PARAMETERS_END()
17+
#endif
18+
19+
ZEND_BEGIN_MODULE_GLOBALS(nop)
20+
char *ignore_functions;
21+
ZEND_END_MODULE_GLOBALS(nop)
22+
23+
ZEND_DECLARE_MODULE_GLOBALS(nop)
24+
25+
#ifdef ZTS
26+
#define NOP_G(v) ZEND_TSRMG(nop_globals_id, zend_nop_globals *, v)
27+
#else
28+
#define NOP_G(v) (nop_globals.v)
29+
#endif
30+
31+
static void php_nop_init_globals(zend_nop_globals *nop_globals)
32+
{
33+
nop_globals->ignore_functions = NULL;
34+
}
35+
36+
PHP_FUNCTION(no_operation)
37+
{
38+
// Do nothing
39+
}
40+
41+
/* {{{ PHP_RINIT_FUNCTION */
42+
PHP_RINIT_FUNCTION(nop)
43+
{
44+
#if defined(ZTS) && defined(COMPILE_DL_NOP)
45+
ZEND_TSRMLS_CACHE_UPDATE();
46+
#endif
47+
48+
return SUCCESS;
49+
}
50+
/* }}} */
51+
52+
PHP_INI_BEGIN()
53+
STD_PHP_INI_ENTRY("nop.ignore_functions", "", PHP_INI_ALL, OnUpdateString, ignore_functions, zend_nop_globals, nop_globals)
54+
PHP_INI_END()
55+
56+
/* {{{ PHP_MINIT_FUNCTION */
57+
PHP_MINIT_FUNCTION(nop)
58+
{
59+
ZEND_INIT_MODULE_GLOBALS(nop, php_nop_init_globals, NULL);
60+
REGISTER_INI_ENTRIES();
61+
62+
char *ignore_functions = NOP_G(ignore_functions);
63+
if (ignore_functions != NULL) {
64+
char *token;
65+
char *rest = ignore_functions;
66+
while ((token = strtok_r(rest, ",", &rest))) {
67+
zend_function *original;
68+
original = zend_hash_str_find_ptr(CG(function_table), token, strlen(token));
69+
70+
if (original != NULL) {
71+
original->internal_function.handler = PHP_FN(no_operation);
72+
}
73+
}
74+
}
75+
76+
return SUCCESS;
77+
}
78+
/* }}} */
79+
80+
/* {{{ PHP_MSHUTDOWN_FUNCTION */
81+
PHP_MSHUTDOWN_FUNCTION(nop)
82+
{
83+
UNREGISTER_INI_ENTRIES();
84+
}
85+
/* }}} */
86+
87+
/* {{{ PHP_MINFO_FUNCTION */
88+
PHP_MINFO_FUNCTION(nop)
89+
{
90+
php_info_print_table_start();
91+
php_info_print_table_row(2, "nop support", "enabled");
92+
php_info_print_table_end();
93+
}
94+
/* }}} */
95+
96+
/* {{{ nop_module_entry */
97+
zend_module_entry nop_module_entry = {
98+
STANDARD_MODULE_HEADER,
99+
"nop", /* Extension name */
100+
ext_functions, /* zend_function_entry */
101+
PHP_MINIT(nop), /* PHP_MINIT - Module initialization */
102+
PHP_MSHUTDOWN(nop), /* PHP_MSHUTDOWN - Module shutdown */
103+
PHP_RINIT(nop), /* PHP_RINIT - Request initialization */
104+
NULL, /* PHP_RSHUTDOWN - Request shutdown */
105+
PHP_MINFO(nop), /* PHP_MINFO - Module info */
106+
PHP_NOP_VERSION, /* Version */
107+
STANDARD_MODULE_PROPERTIES
108+
};
109+
/* }}} */
110+
111+
#ifdef COMPILE_DL_NOP
112+
# ifdef ZTS
113+
ZEND_TSRMLS_CACHE_DEFINE()
114+
# endif
115+
ZEND_GET_MODULE(nop)
116+
#endif

nop.stub.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
/**
4+
* @generate-class-entries
5+
* @undocumentable
6+
*/
7+
8+
function no_operation(): void {}

nop_arginfo.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* This is a generated file, edit the .stub.php file instead.
2+
* Stub hash: 54b0ffc3af871b189435266df516f7575c1b9675 */
3+
4+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(no_operation, 0, 0, IS_VOID, 1)
5+
ZEND_END_ARG_INFO()
6+
7+
ZEND_FUNCTION(no_operation);
8+
9+
static const zend_function_entry ext_functions[] = {
10+
ZEND_FE(no_operation, no_operation)
11+
ZEND_FE_END
12+
};

php_nop.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* nop extension for PHP */
2+
3+
#ifndef PHP_NOP_H
4+
# define PHP_NOP_H
5+
6+
extern zend_module_entry nop_module_entry;
7+
# define phpext_nop_ptr &nop_module_entry
8+
9+
# define PHP_NOP_VERSION "0.1.0"
10+
11+
# if defined(ZTS) && defined(COMPILE_DL_NOP)
12+
ZEND_TSRMLS_CACHE_EXTERN()
13+
# endif
14+
15+
#endif /* PHP_NOP_H */

tests/001.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Check if nop is loaded
3+
--EXTENSIONS--
4+
nop
5+
--FILE--
6+
<?php
7+
echo 'The extension "nop" is available';
8+
?>
9+
--EXPECT--
10+
The extension "nop" is available

tests/002.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
no_operation() Basic test
3+
--EXTENSIONS--
4+
nop
5+
--FILE--
6+
<?php
7+
no_operation();
8+
?>
9+
--EXPECT--
10+

0 commit comments

Comments
 (0)