From: Mathias Bartmann <mathias.bartmann@gmail.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH proxmox-acme 3/3] tests: rewrite check-missing-functions to catch calls in substitutions
Date: Fri, 25 Sep 2026 14:47:37 +0200 [thread overview]
Message-ID: <20260925124737.42866-4-mathias.bartmann@gmail.com> (raw)
In-Reply-To: <20260925124737.42866-1-mathias.bartmann@gmail.com>
The check did not notice the missing _json_decode, _mktemp and
_url_replace helpers, for two reasons:
- it only matched a _name followed by a space, so calls at the end of
a command substitution or pipe like "$(_mktemp)" or "| _json_decode)"
were never seen
- it filtered whole lines, so any line that also contains an
assignment, like "_tmp_file=$(_mktemp)", was dropped
Rewrite it in Perl to extract each _name in command position (line
start, after ( ` | ; & ! or a shell keyword, not followed by '='),
skipping arithmetic like "$((_cnt - 1))", and report the ones defined
neither in proxmox-acme nor in the calling plugin. Checked against the
tree before the respective fixes, this reports dns_active24.sh:
_json_decode, dns_oci.sh and dns_transip.sh: _mktemp, and dns_yc.sh:
_url_replace.
The false positives of the old check are gone, so the expected list
shrinks to dns_aws.sh calling _error, which upstream acme.sh does not
define either.
Signed-off-by: Mathias Bartmann <mathias.bartmann@gmail.com>
---
src/test/check-missing-functions | 59 ++++++++++++++++++++++++-----
src/test/missing-functions.expected | 8 +---
2 files changed, 50 insertions(+), 17 deletions(-)
diff --git a/src/test/check-missing-functions b/src/test/check-missing-functions
index dfc32d3..adb93cd 100755
--- a/src/test/check-missing-functions
+++ b/src/test/check-missing-functions
@@ -1,14 +1,53 @@
-#!/bin/sh
+#!/usr/bin/perl
-set -e
+use strict;
+use warnings;
-# functions already in src/proxmox-acme
-PRESENT=$(awk 'BEGIN{ORS="\\W|";} /^_/{ gsub(/\(\) {/, ""); print $0}' \
- ../proxmox-acme | sed -r 's/\|$//')
+# Print every _helper a dnsapi plugin calls that is defined neither in
+# src/proxmox-acme nor in the plugin itself.
-# functions defined in all plugins
-LOCAL=$(awk 'BEGIN{ORS="\\W|";} /^_/{ gsub(/\(\) {/, ""); print $0}' \
- ../acme.sh/dnsapi/dns*.sh | sed -r 's/\|$//')
+my $shim_path = '../proxmox-acme';
+my $dnsapi_path = '../acme.sh/dnsapi';
-grep -P '(?<!["$])\b_[a-zA-Z0-9_-]+ ' ../acme.sh/dnsapi/dns_*sh | \
- grep -Ev "$PRESENT|$LOCAL|\b_[a-zA-Z0-9_-]+=|^../acme.sh/dnsapi/.*sh: *#"
+die "cannot find '$shim_path'!\n" if !-f $shim_path;
+die "cannot find dnsapi path '$dnsapi_path'!\n" if !-d $dnsapi_path;
+
+sub defined_functions {
+ my ($path) = @_;
+
+ open(my $fh, '<', $path) or die "cannot open '$path' - $!\n";
+ my $functions = {};
+ while (my $line = <$fh>) {
+ $functions->{$1} = 1 if $line =~ /^\s*(_[A-Za-z0-9_]+)\s*\(\)/;
+ }
+ close($fh);
+
+ return $functions;
+}
+
+# a _word in command position: at line start, after ( ` | ; & ! or a shell
+# keyword, and not followed by '=' (an assignment) - this also covers calls
+# inside command substitutions like "$(_mktemp)" and pipes like "| _dbase64",
+# but not variables in arithmetic like "$((_cnt - 1))"
+my $call_re = qr/
+ (?: ^ | (?<!\()\((?!\() | [`|;&!] | \b(?:if|then|else|elif|do|while|until)\s )
+ \s* (_[A-Za-z0-9_]+) (?= [\s)`|;&] | $ )
+/x;
+
+my $shim_functions = defined_functions($shim_path);
+
+for my $plugin (sort glob("$dnsapi_path/dns_*.sh")) {
+ my $plugin_functions = defined_functions($plugin);
+
+ open(my $fh, '<', $plugin) or die "cannot open '$plugin' - $!\n";
+ my $reported = {};
+ while (my $line = <$fh>) {
+ next if $line =~ /^\s*#/;
+ while ($line =~ /$call_re/g) {
+ my $function = $1;
+ next if $shim_functions->{$function} || $plugin_functions->{$function};
+ print "$plugin: $function\n" if !$reported->{$function}++;
+ }
+ }
+ close($fh);
+}
diff --git a/src/test/missing-functions.expected b/src/test/missing-functions.expected
index b338a58..c8f8240 100644
--- a/src/test/missing-functions.expected
+++ b/src/test/missing-functions.expected
@@ -1,7 +1 @@
-../acme.sh/dnsapi/dns_artfiles.sh: response="$(printf -- '%s' "$response" | sed '/_acme-challenge "'"$txtValue"'"/d')"
-../acme.sh/dnsapi/dns_aws.sh: _error "invalid domain"
-../acme.sh/dnsapi/dns_cpanel.sh: for _domain in $_domains; do
-../acme.sh/dnsapi/dns_cyon.sh: printf "%s" "${_dns_entries}" | while read -r _hash _identifier; do
-../acme.sh/dnsapi/dns_mythic_beasts.sh: export _H1 _H2
-../acme.sh/dnsapi/dns_openstack.sh: for _rec in $_records; do
-../acme.sh/dnsapi/dns_selectel.sh: for _one_id in $_record_id; do
+../acme.sh/dnsapi/dns_aws.sh: _error
--
2.55.0
prev parent reply other threads:[~2026-09-28 7:16 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 12:47 [PATCH proxmox-acme 0/3] acme: fix missing/diverging shim helpers, tighten missing-function check Mathias Bartmann
2026-09-25 12:47 ` [PATCH proxmox-acme 1/3] fix #7851: acme: add missing _mktemp and restore _dbase64 default Mathias Bartmann
2026-09-25 12:47 ` [PATCH proxmox-acme 2/3] acme: add missing _url_replace function Mathias Bartmann
2026-09-25 12:47 ` Mathias Bartmann [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260925124737.42866-4-mathias.bartmann@gmail.com \
--to=mathias.bartmann@gmail.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.