33%{
44#include " libinjection.h"
55#include " libinjection_sqli.h"
6+ #include " libinjection_xss.h"
7+ #include " libinjection_error.h"
68#include < stddef.h>
9+ #include < string.h>
710
811/* This is the callback function that runs a python function
912 *
@@ -13,26 +16,45 @@ static char libinjection_python_check_fingerprint(sfilter* sf, int lookuptype, c
1316 PyObject *fp;
1417 PyObject *arglist;
1518 PyObject *result;
16- const char * strtype;
1719 char ch;
1820
1921 // get sfilter->pattern
2022 // convert to python string
2123 fp = SWIG_InternalNewPointerObj ((void *)sf, SWIGTYPE_p_libinjection_sqli_state,0 );
2224
23- arglist = Py_BuildValue (" (Nis#)" , fp, lookuptype, word, len);
25+ // Use y# (bytes) format instead of s# (str) to avoid UnicodeDecodeError on
26+ // non-UTF-8 bytes (e.g. 0xA0 word separators). The Python callback will
27+ // receive the word as a bytes object and should decode it as needed.
28+ arglist = Py_BuildValue (" (Niy#)" , fp, lookuptype, word, len);
29+ if (arglist == NULL ) {
30+ // Py_BuildValue failed (e.g., encoding error); treat as not found
31+ return ' \0 ' ;
32+ }
2433 // call pyfunct with string arg
2534 result = PyObject_CallObject ((PyObject*) sf->userdata , arglist);
2635 Py_DECREF (arglist);
2736 if (result == NULL ) {
28- printf (" GOT NULL\n " );
2937 // python call has an exception
3038 // pass it back
3139 ch = ' \0 ' ;
3240 } else {
33- // convert value of python call to a char
34- strtype = PyString_AsString (result);
35- ch = strtype[0 ];
41+ // convert value of python call to a char (Python 3 compatible)
42+ if (PyUnicode_Check (result)) {
43+ Py_ssize_t size;
44+ const char * str = PyUnicode_AsUTF8AndSize (result, &size);
45+ if (str != NULL && size > 0 ) {
46+ ch = str[0 ];
47+ } else {
48+ // Clear any exception set by PyUnicode_AsUTF8AndSize on failure
49+ PyErr_Clear ();
50+ ch = ' \0 ' ;
51+ }
52+ } else if (PyBytes_Check (result)) {
53+ const char * str = PyBytes_AsString (result);
54+ ch = (str != NULL ) ? str[0 ] : ' \0 ' ;
55+ } else {
56+ ch = ' \0 ' ;
57+ }
3658 Py_DECREF (result);
3759 }
3860 return ch;
@@ -65,8 +87,61 @@ for (i = 0; i < $1_dim0; i++) {
6587}
6688}
6789
68- // automatically append string length into arg array
69- %apply (char *STRING, size_t LENGTH) { (const char *s, size_t slen) };
90+ // automatically append string length into arg array.
91+ // Accept both str (encoded as UTF-8) and bytes (passed through as-is).
92+ // Using bytes is recommended when the input may contain non-ASCII octets,
93+ // since str will be UTF-8 encoded which changes the byte values.
94+ %typemap(in) (const char *s, size_t slen) (Py_buffer _view, int _must_release) {
95+ _must_release = 0 ;
96+ if (PyBytes_Check ($input)) {
97+ if (PyObject_GetBuffer ($input, &_view, PyBUF_SIMPLE) != 0 ) SWIG_fail;
98+ $1 = (const char *)_view.buf ;
99+ $2 = (size_t )_view.len ;
100+ _must_release = 1 ;
101+ } else if (PyUnicode_Check ($input)) {
102+ Py_ssize_t _len;
103+ $1 = PyUnicode_AsUTF8AndSize ($input, &_len);
104+ if (!$1 ) SWIG_fail;
105+ $2 = (size_t )_len;
106+ } else {
107+ PyErr_SetString (PyExc_TypeError, " expected str or bytes" );
108+ SWIG_fail;
109+ }
110+ }
111+ %typemap(freearg) (const char *s, size_t slen) {
112+ if (_must_release$argnum) PyBuffer_Release (&_view$argnum);
113+ }
114+ %typemap(in) (const char *s, size_t len) (Py_buffer _view, int _must_release) {
115+ _must_release = 0 ;
116+ if (PyBytes_Check ($input)) {
117+ if (PyObject_GetBuffer ($input, &_view, PyBUF_SIMPLE) != 0 ) SWIG_fail;
118+ $1 = (const char *)_view.buf ;
119+ $2 = (size_t )_view.len ;
120+ _must_release = 1 ;
121+ } else if (PyUnicode_Check ($input)) {
122+ Py_ssize_t _len;
123+ $1 = PyUnicode_AsUTF8AndSize ($input, &_len);
124+ if (!$1 ) SWIG_fail;
125+ $2 = (size_t )_len;
126+ } else {
127+ PyErr_SetString (PyExc_TypeError, " expected str or bytes" );
128+ SWIG_fail;
129+ }
130+ }
131+ %typemap(freearg) (const char *s, size_t len) {
132+ if (_must_release$argnum) PyBuffer_Release (&_view$argnum);
133+ }
134+
135+ // Make the fingerprint output parameter in libinjection_sqli() work as an output
136+ // The fingerprint buffer size matches libinjection's internal LIBINJECTION_SQLI_MAX_TOKENS (5) + null byte
137+ #define LIBINJECTION_FINGERPRINT_SIZE 8
138+ %typemap(in, numinputs=0 ) char fingerprint[] (char temp[LIBINJECTION_FINGERPRINT_SIZE]) {
139+ memset (temp, 0 , sizeof (temp));
140+ $1 = temp;
141+ }
142+ %typemap(argout) char fingerprint[] {
143+ $result = SWIG_Python_AppendOutput ($result, PyUnicode_FromString ($1 ));
144+ }
70145
71146%typemap(in) (ptr_lookup_fn fn, void * userdata) {
72147 if ($input == Py_None) {
@@ -77,5 +152,7 @@ for (i = 0; i < $1_dim0; i++) {
77152 $2 = $input;
78153 }
79154}
155+ %include " libinjection_error.h"
80156%include " libinjection.h"
81157%include " libinjection_sqli.h"
158+ %include " libinjection_xss.h"
0 commit comments