Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(lib): do not insert "nulls" as values for __VARARGS__ config arguments #254

Merged
merged 1 commit into from
Oct 16, 2024

Conversation

OverOrion
Copy link
Contributor

@OverOrion OverOrion commented Aug 13, 2024

@version: current

block destination second(...) {
      `__VARARGS__`
};

block destination first(...) {
      second(`__VARARGS__`);
};

log {
   destination{ first(some-param("")) };
};

After the fix:

[2024-10-15T09:49:23.089776] Unknown argument, adding it to __VARARGS__; argument='some_param', value='', reference='../install_dir/etc/empty.conf:12:17'
[2024-10-15T09:49:23.089776] Unknown argument, adding it to __VARARGS__; argument='some_param', value='', reference='../install_dir/etc/empty.conf:8:7'

Error parsing log statement: syntax error, unexpected LL_IDENTIFIER, expecting '}'

In ../install_dir/etc/empty.conf:4:7-4:17:
-1      
0       #Start Block block destination second() at ../install_dir/etc/empty.conf:3
1       ## some_param=
2       @line "../install_dir/etc/empty.conf" 3 31
3       
4----->       some_param("") 
4----->       ^^^^^^^^^^
5       
6       #End Block block destination second() at ../install_dir/etc/empty.conf:3
7       

Included from ../install_dir/etc/empty.conf:8:7-8:30:
3       
4       #Start Block block destination first() at ../install_dir/etc/empty.conf:7
5       ## some_param=
6       @line "../install_dir/etc/empty.conf" 7 30
7       
8----->       second(some_param("") );
8----->       ^^^^^^^^^^^^^^^^^^^^^^^
9       
10      #End Block block destination first() at ../install_dir/etc/empty.conf:7
11      

Included from ../install_dir/etc/empty.conf:12:17-12:38:
7       block destination first(...) {
8             second(`__VARARGS__`);
9       };
10      
11      log {
12---->    destination{ first(some-param("")) };
12---->                 ^^^^^^^^^^^^^^^^^^^^^
13      };

Fixes #244.

furiel
furiel previously approved these changes Aug 13, 2024
@OverOrion
Copy link
Contributor Author

On a second thought this might not be a proper fix:

[2024-08-13T09:19:13.979827] Unknown argument, adding it to __VARARGS__; argument='some_param', value='', reference='/source/install_dir/etc/foo.conf:12:17'
[2024-08-13T09:19:13.979827] Unknown argument, adding it to __VARARGS__; argument='some_param', value='(null)', reference='/source/install_dir/etc/foo.conf:8:7'

The value gets lost somewhere 👀

Copy link
Member

@MrAnno MrAnno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I remember this only happens through multi-level passes of __VARARGS__ with empty values, so the real fix might be somewhere else and will be something about how we handle the empty string parameter passed through these varargs.

@alltilla
Copy link
Member

alltilla commented Sep 6, 2024

Another config that crashes at the same location:

@version: current

block destination a(filtr(def)) {
  channel {
    filter {
      `filtr`
      and 1 == 1};
  };
};

destination d { a(filtr()); };

lib/cfg-block-generator.c Outdated Show resolved Hide resolved
@OverOrion
Copy link
Contributor Author

OverOrion commented Oct 15, 2024

Updated the PR to properly handle empty __VARARGS__ values instead.

@OverOrion OverOrion changed the title fix(lib): check generator_args value before using it fix(lib): do not insert "nulls" as values for __VARARGS__ config arguments Oct 15, 2024
@MrAnno
Copy link
Member

MrAnno commented Oct 15, 2024

This is getting closer, it fixes the crash with the above config snippet but changes the output if you type some-param() to some-param("") inside the block (but it crashes before that because of the same null-ptr deref issue).

I think the issue is in the lexer, it removes "" when passing parameters.
I'm investigating this and propose my patch soon.

@MrAnno
Copy link
Member

MrAnno commented Oct 15, 2024

<block>\({white}*\)        { yy_pop_state(yyscanner); yylval->cptr = NULL; return LL_BLOCK; }
<block>\({white}*\"\"{white}*\) { yy_pop_state(yyscanner); yylval->cptr = g_strdup(""); return LL_BLOCK; }
<block>\({white}*\'\'{white}*\) { yy_pop_state(yyscanner); yylval->cptr = g_strdup(""); return LL_BLOCK; }

These are the ones removing what we need.
The problem here is probably the context of where we use these:

  • we need to remove empty quotes in the declaration of block params (that's how we detect "optional" and "mandatory")
  • we should NOT remove quotes when we pass arguments to blocks (when we "call" them) it's more complicated than that.

@MrAnno
Copy link
Member

MrAnno commented Oct 15, 2024

I can't fix this without reimplementing f0650bb completely, which would be a lot more work.

syslog-ng/syslog-ng#2088 (comment) says the following:

As "" is not mapped into "" anymore, this is a problem needs to be addressed. Luckily, we could break the cycle here, do not need to find another symbol that would be mapped to "", of which again find a symbol that maps to the underlying symbol etc. This can be addressed by modifying such scl. I show an example for this:

Unfortunately, this is not so lucky with varargs. With the current implementation, it is impossible to pass an empty string parameter through varargs. With your current patch, it is possible, but then it breaks the fully empty case.

So in order to fix the crash (but without making it possible to pass empty strings properly), I think we could go with this (which is very similar to your original patch, except for the new-line ending):

diff --git a/lib/cfg-block-generator.c b/lib/cfg-block-generator.c
index 9374c58e8..00811f278 100644
--- a/lib/cfg-block-generator.c
+++ b/lib/cfg-block-generator.c
@@ -39,6 +39,7 @@ _report_generator_args(gpointer key, gpointer value, gpointer user_data)
 {
   GString *result = (GString *) user_data;
   g_string_append_printf(result, "## %s=", (gchar *) key);
+  value = value ? : "";
   for (const gchar *c = (const gchar *) value; *c; c++)
     {
       if (*c == '\n' && *(c + 1))

Because of this:

if (!_append_value(self, value ? : "", error))

And we can open a separate issue about the impossibility to pass empty strings through varargs.
@OverOrion Is that okay with you?

OverOrion added a commit that referenced this pull request Oct 16, 2024
This avoids crashing if `NULL` (==empty string) was passed as value.
For details see #254 (comment)
This avoids crashing if `NULL` (==empty string) was passed as value.
For details see #254 (comment)

Signed-off-by: Szilard Parrag <[email protected]>
@MrAnno MrAnno merged commit fbd0d0f into main Oct 16, 2024
43 checks passed
@MrAnno MrAnno deleted the fix-varargs-null-deref branch October 16, 2024 07:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

crash while passing an empty parameter through chain of scl blocks
5 participants