1. 15 Feb, 2021 5 commits
    • Guillaume Quintard's avatar
      [cci] work around glibc bug · 1d5c0aae
      Guillaume Quintard authored
      1d5c0aae
    • Nils Goroll's avatar
      Enable calling a dynamic sub · 7ec28f1a
      Nils Goroll authored
      that is,
      
      	call vmod.returning_sub();
      
      in VCL.
      
      Background:
      
      The existing
      
      	call sub;
      
      is special in that it instantiates "sub", if it does not exist
      already, enabling use-before-definition semantics.
      
      The doctrine of this change is to preserve this behaviour and to not
      make existing, static calls any less efficient.
      
      Implementation:
      
      To support calling both literal SUBs as well as SUB expressions, we
      peek into the symbol table to check if the called expression is a
      function, based on the knowledge that, as of now, only functions can
      have a non-literal SUB return. We also know that no other expression
      can yield a SUB. So if peeking ahead tells us that a function follows,
      we call into expression evaluation.
      
      Otherwise, we expect a literal SUB as before.
      
      Null check:
      
      For dynamic SUB calls from vmods via VRT_call(), we require the SUB
      argument be non-NULL. But we can not for call: To signal error with a
      SUB return, a vmod function needs to be allowed to return NULL,
      otherwise it would need to have a dummy return value available for the
      VRT_fail() case. So we need to check for NULL in VGC.
      
      Alternatives considered:
      
      - We could make expression evaluation return SUB also for literal SUB
      symbols, turning all calls into sub->func(ctx, ...) C statements. I
      tried this path and it resulted in a change of behaviour with
      cc_command="clang -g -O2 ...": Where, previously, sub code was
      inlined, it would now generate an explicit C function call always,
      despite the fact that the C function is known at compile time (because
      all named VCL_SUB structs are).
      
      So this option was dismissed for violating the doctrine.
      
      - The null check could go to VPI, via a VPI_call(), basically identical
      to VRT_call(), but checking for NULL. This option was dismissed because
      it would foreclose the requirement to allow for SUB arguments in the
      future.
      
      Acknowledgements:
      
      reza mentioned the idea of call SUB at one point, and I can not remember
      if I had it before or not, so when in doubt, it was his idea.
      
      Dridi helped with ideas on the implementation and spotted a bug.
      7ec28f1a
    • Dridi Boukelmoune's avatar
      param: New vary_notice parameter · e74abf89
      Dridi Boukelmoune authored
      To control the threshold used to warn.
      e74abf89
    • Dridi Boukelmoune's avatar
      lookup: Add a notice for high numbers of variants · ce9fbe44
      Dridi Boukelmoune authored
      As a recurring pitfall sometimes hard to identify, it deserves its own
      notice. The accounting of variants reuses the worker's strangelove field
      since it doesn't conflict where other parts of the code base use it.
      ce9fbe44
    • Poul-Henning Kamp's avatar
  2. 12 Feb, 2021 5 commits
  3. 11 Feb, 2021 5 commits
  4. 10 Feb, 2021 5 commits
  5. 09 Feb, 2021 9 commits
  6. 08 Feb, 2021 11 commits
    • Nils Goroll's avatar
      fix changelog oops · 8cddd051
      Nils Goroll authored
      We cannot :ref: the rest of the online documentation from here
      8cddd051
    • Nils Goroll's avatar
      Add VRT_handled(), use it in VRT_call() and add red tape... · ff18a3c5
      Nils Goroll authored
      ... regarding multiple VRT_call()s from vmods.
      
      Dridi noticed that we need to consider the handling for VRT_call(),
      thank you!
      ff18a3c5
    • Nils Goroll's avatar
      Polish 59034c01 · 3aff2257
      Nils Goroll authored
      Based on feedback from Dridi
      3aff2257
    • Nils Goroll's avatar
      flexelint bba4b145 · cdadc4be
      Nils Goroll authored
      cdadc4be
    • Nils Goroll's avatar
      Add m00054.vtc: panic when calling sub from a wrong vcl · af889452
      Nils Goroll authored
      VMODs must not use SUB references across VCLs. This test checks for a
      panic if they do.
      af889452
    • Nils Goroll's avatar
      Add m00053.vtc: Test dynamic calls · 9046707c
      Nils Goroll authored
      This test case checks dynamic calls, and, in particular, the runtime
      context checks and recursion detection. Recursions have to be caught at
      the first instance.
      
      Also test interop with the PRIV_TOP compile time restriction
      
      Ref #3498
      Ref 6d49b18f
      
      The test has been manually annotated with information regarding the
      results expted from VCCs call tree walk.
      
      Explanation:
      
      .called == call, but every walk counts (for instance, barbarbar can be
      reached twice, via bar and barbar)
      
      .nref == sum(refs): Each VCL ref gains a ref, and each call from a sub
      which is itself dynamic (has nref > called).
      9046707c
    • Nils Goroll's avatar
      Support dynamic SUBs with VRT_call() / VRT_check_call() · 06696692
      Nils Goroll authored
      This allows for VCL subs to be called dynamically at runtime: vmods
      may store references to VCL_SUBs and call them some time later.
      
      Calling a VCL_SUB pointer requires to conduct two fundamental checks
      also at runtime, which previously were implemented by VCC at compile
      time only:
      
      * checking the allowed context
      * checking for recursive calls
      
      The foundation for both has been laid in previous commits and has
      been made available through VPI_Call_*().
      
      Note that we do not change the VCC checks in any way for static calls,
      we only add runtime checks for dynamic calls.
      
      This commit adds a VRT interface for dynamic calls and changes VGC to
      ensure proper runtime checking (as suggested by phk).
      
      We add to the vcl_func_f signature
      - a vcl_func_call_e argument denoting the type of call and
      - a vcl_func_fail_e value argument to optionally return a failure code
      
      On vcl_func_call_e:
      
      VSUB_CHECK allows runtime callers to preflight a "can this sub be
      called" check, which is the basis for VRT_check_call().
      
      VSUB_DYNAMIC must be used by any calls outside VGC.
      
      VSUB_STATIC is for VGC only and, strictly speaking, would not be
      required. It is added for clarity and safety and used for "call"
      actions from VCL.
      
      On vcl_func_fail_e:
      
      If the argument is present, any error will be returned in
      it. Otherwise, the generated code fails the VCL.
      
      On the implementation:
      
      To minimize the overhead for runtime context and recursion checks, we
      only add them where needed.
      
      In previous commits, we changed the VCC walks over SUBs to ensure that
      any dynamically referenced SUBs and all SUBs reachable from these via
      "call" can be identified by having more references than calls
      (p->sym->nref > p->called).
      
      So we now know, at compile time, for which SUBs we need to add runtime
      checks. Read
      https://github.com/varnishcache/varnish-cache/pull/3163#issuecomment-770266098
      for more details.
      
      Depending on whether the SUB is dynamically callable or not, we either
      add runtime checks or keep the code identical to before (except for a
      changed signature and some assertions).
      
      For the dynamic case, we need to wrap the actual SUB in order to clear
      the recursion check bit when it returns. Note that this happens
      independend of whether the actuall call is static or dynamic - because
      it has to. The recursion check for dynamic calls requires any previous
      static calls to be registered.
      
      The VGC for the dynamic case looks like this (slightly edited for
      clarity):
      
      static void
      VGC_function_foo_checked(VRT_CTX)
      {
        assert(ctx->method & (VCL_MET_DELIVER|VCL_MET_SYNTH));
        { { VPI_count(ctx, 1);
            // ... as before
      
      void v_matchproto_(vcl_func_f)
      VGC_function_foo(VRT_CTX, enum vcl_func_call_e call,
          enum vcl_func_fail_e *failp)
      {
        enum vcl_func_fail_e fail;
      
        fail = VPI_Call_Check(ctx, &VCL_conf, 0x300, 0);
        if (failp)
          *failp = fail;
        else if (fail == VSUB_E_METHOD)
          VRT_fail(ctx, "call to \"sub foo{}\" not allowed from here");
        else if (fail == VSUB_E_RECURSE)
          VRT_fail(ctx, "Recursive call to \"sub foo{}\" not allowed from here");
        else
          assert(fail == VSUB_E_OK);
      
        if (fail != VSUB_E_OK || call == VSUB_CHECK)
          return;
        VPI_Call_Begin(ctx, 0);
        VGC_function_foo_checked(ctx);
        VPI_Call_End(ctx, 0);
      }
      
      The actual function body remains unchanged, but is contained in the
      static function named "*_checked". The vcl_func_f is now a wrapper.
      
      The wrapper
      
      - checks for context errors using VPI_Call_Check()
      - either returns any error in the failp argument or fails the VCL
      - encoses the call to the "_checked" function with VPI_Call_Begin /
        VPI_Call_End which set/clear the recursion marker bit.
      06696692
    • Nils Goroll's avatar
      Add VPI interface for runtime recursion tracking & checks · a91e16ed
      Nils Goroll authored
      This implements the first bit of phks suggestion in
      https://github.com/varnishcache/varnish-cache/pull/3163#issuecomment-769718143
      
      These VPI functions implement the operations on the recursion check
      bitmask for dynamic SUB calls. Strictly speaking, the VPI subs would
      not need to be concerned with the methods bitmask check and the
      assertion that calls originate from the right VCL, but we centralise
      these aspects for simplicity.
      
      We also add an enum to denote check failures.
      a91e16ed
    • Nils Goroll's avatar
      Add a bitmask tracking SUB calls to detect recursions · a294c31d
      Nils Goroll authored
      To allow dynamic SUB calls, we need to check for recursions at
      runtime, reflecting the compile time recursion check.
      
      We create a bitmask to note each dynamically called SUB by its unique
      number. To check for recursions, we only need to test if the
      respective bit for the sub number is already set.
      
      We only conduct this check if the track_call argument of
      vcl_call_method() is true. By setting this argument to the number of
      SUB references, we enable call tracking only for VCLs with dynamic SUB
      references (when (struct VCL_conf).nsub is non-zero).
      
      VCC already guarantees that static calls are loop free - so loops can
      only be introduced through dynamic SUB references.
      
      Call tracking with a bitmask was suggested by phk
      a294c31d
    • Nils Goroll's avatar
      vgc: Advise C compiler not optimize housekeeping subs *only* · 8551b1f5
      Nils Goroll authored
      Before the addition of the okmask, we could only selectively turn off
      optimizations for the built-in housekeeping subs (vcl_init {} /
      vcl_fini {}), not for any custom subs called from there.
      
      The previous commit changed this and turned off optimizations for any
      custom subs called from there.
      
      We pull this tighter again by only turning off optimizations for subs
      which can _only_ be called from housekeeping.
      
      Ref f1c47e48
      Ref #3230
      8551b1f5
    • Nils Goroll's avatar
      vgc: Assert on ctx->method also for custom subs · 7574ac63
      Nils Goroll authored
      Improve safety by asserting that a sub is never called from a context
      which is not allowed as per its okmask.
      
      This is to ensure correctness of our compile- and runtime-checks.
      7574ac63