Conversion of Function to Number possible on certain platforms
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 2.2k
- Forks
- 616
- Avg merge
- 5d 6h
- Merged PRs (30d)
- 10
Description
Describe the bug
It is possible to convert an Icinga function to a Number on certain platforms.
- ✅ Linux built with glibc:
Icinga 2 (version: v2.14.0-566-g8d607d2ef) Type $help to view available commands. <1> => Number({{ }}) ^^^^^^^^^^^^^ Error while evaluating expression: Can't convert 'Object of type 'Function'' to a floating point number. - ✅ Linux built with musl:
Icinga 2 (version: r2.14.0-1) Type $help to view available commands. <1> => Number({{ }}) ^^^^^^^^^^^^^ Error while evaluating expression: Can't convert 'Object of type 'Function'' to a floating point number. - ❌ OpenBSD 7.7:
Icinga 2 (version: r2.14.5-1) Type $help to view available commands. <1> => Number({{ }}) 14088953728896.000000 - ❌ macOS (24.5.0 Darwin Kernel Version 24.5.0: Tue Apr 22 19:54:29 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6030 arm64)
Icinga 2 (version: v2.14.0-661-gae06649e8) Type $help to view available commands. <1> => Number({{ }}) 5317598160.000000
While working with an Icinga a few days back, I realized that I was able to put a lambda as the Service.check_interval value. On this system, this resulted in this function being interpreted as a huge double, effectively killing Icinga DB.
To Reproduce
The easiest way to check is typing Number({{ }}) into the icinga2 console as shown above. In the following, my original finding was reported.
[!NOTE]
I am able to reproduce this issue on the originally affected system, running the latest Icinga 2 release version r2.14.5 on a current OpenBSD. However, I was not able to reproduce this on a Linux based on our Icinga 2 Docker containers. More about this below.
Starting with a generic Service object assigned with an apply for rule based on custom variables. This Service object has a faulty check_interval value of a lambda instead of a double value.
apply Service for (key => config in host.vars.passive_checks) {
name = key
check_command = "dummy"
check_interval = {{ config.contains("check_interval") ? config.check_interval : 7d }}
vars.dummy_state = 3
vars.dummy_text = {{
var service = get_service(macro("$host.name$"), macro("$service.name$"))
var lastCheck = DateTime(service.last_check).to_string()
return "No check results received. Last result time: " + lastCheck
}}
}
(I am aware that the correct config would be check_interval = config.contains("check_interval") ? config.check_interval : 7d. This has nothing to do with the reported issue.)
For demonstration sake, one Host resulting in two such Service objects was created.
object Host "passive-test" {
import "not-a-host"
vars += {
"passive_checks" = {
"backup" = { check_interval = 14d }
"foo" = { }
}
}
}
Let's verify the config.
$ icinga2 daemon -C --dump-objects
[2025-05-27 12:08:36 +0200] information/cli: Icinga application loader (version: r2.14.5-1)
[2025-05-27 12:08:36 +0200] information/cli: Loading configuration file(s).
[2025-05-27 12:08:36 +0200] information/ConfigItem: Committing config item(s).
[2025-05-27 12:08:37 +0200] information/ApiListener: My API identity: REDACTED
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 CheckerComponent.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 8 Hosts.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 Endpoint.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 FileLogger.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 NotificationComponent.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 3 TimePeriods.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 UserGroup.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 3 Zones.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 Downtime.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 IcingaDB.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 2 HostGroups.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 IcingaApplication.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 2 NotificationCommands.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 108 Services.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 231 CheckCommands.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 19 Dependencies.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 116 Notifications.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 7 ServiceGroups.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 2 ApiUsers.
[2025-05-27 12:08:37 +0200] information/ConfigItem: Instantiated 1 ApiListener.
[2025-05-27 12:08:38 +0200] information/ConfigItem: Instantiated 1 ScheduledDowntime.
[2025-05-27 12:08:38 +0200] information/ConfigItem: Instantiated 1 User.
[2025-05-27 12:08:38 +0200] information/ScriptGlobal: Dumping variables to file '/var/cache/icinga2/icinga2.vars'
[2025-05-27 12:08:38 +0200] information/cli: Finished validating the configuration file(s).
After reloading Icinga 2, the Service objects can be queried.
$ icinga2 object list -t Service -n 'passive-test!backup' | grep check_interval
* check_interval = 13949418929536
$ icinga2 object list -t Service -n 'passive-test!foo' | grep check_interval
* check_interval = 13949418927872
And after another reload, again.
$ icinga2 object list -t Service -n 'passive-test!backup' | grep check_interval
* check_interval = 3945424160768
$ icinga2 object list -t Service -n 'passive-test!foo' | grep check_interval
* check_interval = 3945132634240
While these values are ridiculously large and most likely derived from some pointer value, Icinga 2 is happy.
However, Icinga DB is not.
2025-05-27T12:10:13.039+0200 WARN database Can't execute query. Retrying {[...], "errorVerbose": "pq: value for domain uint violates check constraint \"between_0_and_4294967295\"\ncan't perform \"INSERT INTO \\\"service\\\" [...]}
Since this faulty check_interval value will never be "between_0_and_4294967295", this will eventually lead into an Icinga DB crash.
As stated in the info box above, while I am able to reproduce this on the OpenBSD system, this fails with an expected error on a Linux. Since the type within the .ti file is a double, I am receiving an expected error.
icinga2 | [2025-05-27 10:01:21 +0000] critical/config: Error: Error while evaluating expression: Can't convert 'Object of type 'Function'' to a floating point number.
icinga2 | Location: in /etc/icinga2/zones.d/master/04-dummys-services.conf: 60:3-60:95
icinga2 | /etc/icinga2/zones.d/master/04-dummys-services.conf(58):
icinga2 | /etc/icinga2/zones.d/master/04-dummys-services.conf(59): check_command = "dummy"
icinga2 | /etc/icinga2/zones.d/master/04-dummys-services.conf(60): check_interval = {{ config.contains("check_interval") ? config.get("check_interval") : 24h }}
icinga2 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
icinga2 | /etc/icinga2/zones.d/master/04-dummys-services.conf(61):
icinga2 | /etc/icinga2/zones.d/master/04-dummys-services.conf(62): vars.dummy_state = 3
Now, I am puzzled how this can work on one OS while failing on another.
Expected behavior
I would expect a convert error on every operating system.
Your Environment
Include as many relevant details about the environment you experienced the problem in
- Version used (
icinga2 --version): r2.14.5-1 - Operating System and version: OpenBSD 7.7 GENERIC#630 amd64
- Enabled features (
icinga2 feature list): api checker icingadb mainlog notification - Icinga Web 2 version and modules (System - About): -
- Config validation (
icinga2 daemon -C): ✅
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing Number({{ }}) in the icinga2 console on OpenBSD and Linux, then compare the platform-dependent conversion behavior. Trace the expression evaluation and configuration validation path for the Function-to-Number conversion; done means the conversion raises an error consistently on every supported operating system.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100