ffi: fix buffer overrun when padding struct storage
[m6w6/ext-psi] / src / module.c
index 8201d5a19bc77c004473d1f4ce7507be419ca9d7..e7948d8a0e9abec32534e7665797fa6109e65fdf 100644 (file)
@@ -101,7 +101,8 @@ zend_object *psi_object_init(zend_class_entry *ce)
 ZEND_BEGIN_ARG_INFO_EX(ai_psi_dump, 0, 0, 0)
        ZEND_ARG_INFO(0, stream)
 ZEND_END_ARG_INFO();
-static PHP_FUNCTION(psi_dump) {
+static PHP_FUNCTION(psi_dump)
+{
        php_stream *s;
        zval *r = NULL;
        int fd = STDOUT_FILENO;
@@ -121,50 +122,90 @@ static PHP_FUNCTION(psi_dump) {
 
 ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate, 0, 0, 1)
        ZEND_ARG_INFO(0, file)
+       ZEND_ARG_INFO(0, flags)
 ZEND_END_ARG_INFO();
-static PHP_FUNCTION(psi_validate) {
+static PHP_FUNCTION(psi_validate)
+{
        zend_string *file;
+       struct psi_parser_input *I;
        struct psi_parser P;
        struct psi_data D = {0};
+       zend_long flags = 0;
+
+#if PHP_DEBUG
+       if (psi_check_env("PSI_DEBUG")) {
+               flags |= PSI_DEBUG;
+       }
+#endif
 
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file)) {
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &file, &flags)) {
                return;
        }
 
-       if (!psi_parser_init(&P, file->val, psi_error_wrapper, 0)) {
+       if (!psi_parser_init(&P, psi_error_wrapper, flags)) {
                RETURN_FALSE;
        }
-
-       while (0 < psi_parser_scan(&P)) {
-               psi_parser_parse(&P, psi_token_alloc(&P));
-               if (P.num == PSI_T_EOF) {
-                       break;
-               }
+       if (!(I = psi_parser_open_file(&P, file->val, true))) {
+               psi_parser_dtor(&P);
+               RETURN_FALSE;
        }
-       psi_parser_parse(&P, NULL);
 
+       psi_parser_parse(&P, I);
        psi_data_ctor(&D, P.error, P.flags);
        RETVAL_BOOL(psi_data_validate(&D, PSI_DATA(&P)) && !P.errors);
        psi_data_dtor(&D);
-
        psi_parser_dtor(&P);
+       free(I);
 }
 
-static PHP_MINIT_FUNCTION(psi)
+ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate_string, 0, 0, 1)
+       ZEND_ARG_INFO(0, string)
+ZEND_END_ARG_INFO();
+static PHP_FUNCTION(psi_validate_string)
 {
-       struct psi_context_ops *ops = NULL;
-       zend_class_entry ce = {0};
-       unsigned flags = 0;
+       zend_string *string;
+       struct psi_parser_input *I;
+       struct psi_parser P;
+       struct psi_data D = {0};
+       zend_long flags = 0;
 
+#if PHP_DEBUG
        if (psi_check_env("PSI_DEBUG")) {
                flags |= PSI_DEBUG;
        }
-       if (psi_check_env("PSI_SILENT")) {
-               flags |= PSI_SILENT;
+#endif
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &string, &flags)) {
+               return;
+       }
+
+       if (!psi_parser_init(&P, psi_error_wrapper, flags)) {
+               RETURN_FALSE;
+       }
+       if (!(I = psi_parser_open_string(&P, string->val, string->len))) {
+               psi_parser_dtor(&P);
+               RETURN_FALSE;
        }
 
+       psi_parser_parse(&P, I);
+       psi_data_ctor(&D, P.error, P.flags);
+       RETVAL_BOOL(psi_data_validate(&D, PSI_DATA(&P)) && !P.errors);
+       psi_data_dtor(&D);
+       psi_parser_dtor(&P);
+       free(I);
+}
+
+static PHP_MINIT_FUNCTION(psi)
+{
+       struct psi_context_ops *ops = NULL;
+       zend_class_entry ce = {0};
+       unsigned flags = 0;
+
        REGISTER_INI_ENTRIES();
 
+       zend_register_long_constant(ZEND_STRL("PSI_DEBUG"), PSI_DEBUG, CONST_CS|CONST_PERSISTENT, module_number);
+       zend_register_long_constant(ZEND_STRL("PSI_SILENT"), PSI_SILENT, CONST_CS|CONST_PERSISTENT, module_number);
+
        INIT_NS_CLASS_ENTRY(ce, "psi", "object", NULL);
        psi_class_entry = zend_register_internal_class_ex(&ce, NULL);
        psi_class_entry->create_object = psi_object_init;
@@ -188,18 +229,25 @@ static PHP_MINIT_FUNCTION(psi)
                return FAILURE;
        }
 
+       if (psi_check_env("PSI_DEBUG")) {
+               flags |= PSI_DEBUG;
+       }
+       if (psi_check_env("PSI_SILENT")) {
+               flags |= PSI_SILENT;
+       }
+
        PSI_G(context) = psi_context_init(NULL, ops, psi_error_wrapper, flags);
        psi_context_build(PSI_G(context), PSI_G(directory));
 
-       if (psi_check_env("PSI_DUMP")) {
-               psi_context_dump(PSI_G(context), STDOUT_FILENO);
-       }
-
        return SUCCESS;
 }
 
 static PHP_MSHUTDOWN_FUNCTION(psi)
 {
+       if (psi_check_env("PSI_DUMP")) {
+               psi_context_dump(PSI_G(context), STDOUT_FILENO);
+       }
+
        psi_context_free(&PSI_G(context));
 
        UNREGISTER_INI_ENTRIES();
@@ -247,6 +295,7 @@ static PHP_MINFO_FUNCTION(psi)
 static const zend_function_entry psi_functions[] = {
        PHP_FE(psi_dump, ai_psi_dump)
        PHP_FE(psi_validate, ai_psi_validate)
+       PHP_FE(psi_validate_string, ai_psi_validate_string)
        PHP_FE_END
 };