Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fun getAllAIGeneratedValidators(): Map<Validator, OptionValueInformation> {
Validator("config_parse_bare_udp_iftype", "0") to ConfigParseBareUdpIftypeOptionValue() as OptionValueInformation,
Validator("config_parse_batadv_gateway_mode", "0") to ConfigParseBatadvGatewayModeOptionValue() as OptionValueInformation,
Validator("config_parse_batadv_routing_algorithm", "0") to ConfigParseBatadvRoutingAlgorithmOptionValue() as OptionValueInformation,
Validator("config_parse_bind_network_interface", "0") to ConfigParseBindNetworkInterfaceOptionValue() as OptionValueInformation,
Validator("config_parse_bond_ad_select", "0") to ConfigParseBondAdSelectOptionValue() as OptionValueInformation,
Validator("config_parse_bond_arp_all_targets", "0") to ConfigParseBondArpAllTargetsOptionValue() as OptionValueInformation,
Validator("config_parse_bond_arp_validate", "0") to ConfigParseBondArpValidateOptionValue() as OptionValueInformation,
Expand Down Expand Up @@ -130,6 +131,7 @@ fun getAllAIGeneratedValidators(): Map<Validator, OptionValueInformation> {
Validator("config_parse_macvlan_mode", "0") to ConfigParseMacvlanModeOptionValue() as OptionValueInformation,
Validator("config_parse_managed_oom_mem_pressure_duration_sec", "0") to ConfigParseManagedOomMemPressureDurationSecOptionValue() as OptionValueInformation,
Validator("config_parse_managed_oom_mem_pressure_limit", "0") to ConfigParseManagedOomMemPressureLimitOptionValue() as OptionValueInformation,
Validator("config_parse_managed_oom_rules", "1") to ConfigParseManagedOomRulesOptionValue() as OptionValueInformation,
Validator("config_parse_mdi", "0") to ConfigParseMdiOptionValue() as OptionValueInformation,
Validator("config_parse_pressure_watch", "0") to ConfigParseMemoryPressureWatchOptionValue() as OptionValueInformation,
Validator("config_parse_mtu", "AF_INET6") to ConfigParseMtuOptionValue() as OptionValueInformation,
Expand All @@ -155,10 +157,12 @@ fun getAllAIGeneratedValidators(): Map<Validator, OptionValueInformation> {
Validator("config_parse_prefix_metric", "0") to ConfigParsePrefixMetricOptionValue() as OptionValueInformation,
Validator("config_parse_private_pids", "0") to ConfigParsePrivatePidsOptionValue() as OptionValueInformation,
Validator("config_parse_private_tmp", "0") to ConfigParsePrivateTmpOptionValue() as OptionValueInformation,
Validator("config_parse_private_users", "0") to ConfigParsePrivateUsersOptionValue() as OptionValueInformation,
Validator("config_parse_protect_control_groups", "0") to ConfigParseProtectControlGroupsOptionValue() as OptionValueInformation,
Validator("config_parse_protect_home", "0") to ConfigParseProtectHomeOptionValue() as OptionValueInformation,
Validator("config_parse_protect_system", "0") to ConfigParseProtectSystemOptionValue() as OptionValueInformation,
Validator("config_parse_qfq_weight", "TCLASS_KIND_QFQ") to ConfigParseQfqWeightOptionValue() as OptionValueInformation,
Validator("config_parse_restrict_network_interfaces", "0") to ConfigParseRestrictNetworkInterfacesOptionValue() as OptionValueInformation,
Validator("config_parse_ring_buffer_or_channel", "0") to ConfigParseRingBufferOrChannelOptionValue() as OptionValueInformation,
Validator("config_parse_route_prefix_preference", "0") to ConfigParseRoutePrefixPreferenceOptionValue() as OptionValueInformation,
Validator("config_parse_route_section", "ROUTE_METRIC_FASTOPEN_NO_COOKIE") to ConfigParseRouteSectionOptionValue() as OptionValueInformation,
Expand Down Expand Up @@ -192,12 +196,14 @@ fun getAllAIGeneratedValidators(): Map<Validator, OptionValueInformation> {
Validator("config_parse_unit_condition_string", "CONDITION_CONTROL_GROUP_CONTROLLER") to ConfigParseUnitConditionStringOptionValue() as OptionValueInformation,
Validator("config_parse_unit_condition_string", "CONDITION_CPU_FEATURE") to ConfigParseUnitConditionStringOptionValue() as OptionValueInformation,
Validator("config_parse_unit_condition_string", "CONDITION_FIRST_BOOT") to ConfigParseUnitConditionStringOptionValue() as OptionValueInformation,
Validator("config_parse_unit_env_file", "0") to ConfigParseUnitEnvFileOptionValue() as OptionValueInformation,
Validator("config_parse_unit_slice", "0") to ConfigParseUnitSliceOptionValue() as OptionValueInformation,
Validator("config_parse_use_domains", "0") to ConfigParseUseDomainsOptionValue() as OptionValueInformation,
Validator("config_parse_userns_chown", "0") to ConfigParseUsernsChownOptionValue() as OptionValueInformation,
Validator("config_parse_userns_ownership", "0") to ConfigParseUsernsOwnershipOptionValue() as OptionValueInformation,
Validator("config_parse_vlanid", "0") to ConfigParseVlanidOptionValue() as OptionValueInformation,
Validator("config_parse_vxlan_ttl", "0") to ConfigParseVxlanTtlOptionValue() as OptionValueInformation,
Validator("config_parse_working_directory", "0") to ConfigParseWorkingDirectoryOptionValue() as OptionValueInformation,
Validator("config_parse_wireguard_keepalive", "0") to ConfigParseWireguardKeepaliveOptionValue() as OptionValueInformation,
Validator("config_parse_wireguard_listen_port", "0") to ConfigParseWireguardListenPortOptionValue() as OptionValueInformation,
Validator("config_parse_wireguard_peer_route_priority", "0") to ConfigParseWireguardPeerRoutePriorityOptionValue() as OptionValueInformation,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.*

/**
* Validator for BindNetworkInterface=.
*
* C function: config_parse_bind_network_interface in src/core/load-fragment.c. After
* unit_full_printf specifier expansion, the result must pass ifname_valid_full(
* IFNAME_VALID_ALTERNATIVE) — same rules as RestrictNetworkInterfaces= entries but the value
* is a single interface name (no whitespace-separated list, no leading "~").
*/
class ConfigParseBindNetworkInterfaceOptionValue : SimpleGrammarOptionValues(
"config_parse_bind_network_interface",
SequenceCombinator(
RegexTerminal(
"(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}",
"(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}"
),
EOF()
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.*

/**
* Validator for ManagedOOMRulesets= and friends.
*
* C function: config_parse_managed_oom_rules in src/core/load-fragment.c. After an
* unsupported-unit-type check it tokenizes rvalue with extract_first_word and accepts each
* token that passes string_is_safe(STRING_FILENAME) — i.e. filename-safe characters, not
* "." / "..", no slashes, no whitespace, no shell metacharacters. The rules themselves are
* loaded from .oomrule files at runtime so the grammar only validates the per-token shape.
*/
class ConfigParseManagedOomRulesOptionValue : SimpleGrammarOptionValues(
"config_parse_managed_oom_rules",
SequenceCombinator(
RULE_NAME,
ZeroOrMore(SequenceCombinator(WhitespaceTerminal(), RULE_NAME)),
EOF()
)
) {
companion object {
// STRING_FILENAME forbids slashes, NUL, whitespace, and shell metacharacters. The
// regex below is a conservative ASCII printable set excluding those plus the "." /
// ".." filename reservations (rejected via the negative lookahead).
private val RULE_NAME = RegexTerminal(
"(?!\\.{1,2}\\Z)[A-Za-z0-9._-][A-Za-z0-9._+-]*",
"(?!\\.{1,2}\\Z)[A-Za-z0-9._-][A-Za-z0-9._+-]*"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.*

/**
* Validator for the .nspawn PrivateUsers= setting.
*
* C function: config_parse_private_users in src/nspawn/nspawn-settings.c. Accepts (in order
* the C code checks):
* - boolean ("yes" / "no" / "1" / "0" / "true" / "false" / "on" / "off")
* - "pick" (random UID shift)
* - "identity" (UID shift 0, range 64K)
* - `uid` (single uint32, range defaults to 64K)
* - `uid:range` (two uint32 separated by colon)
*
* Alternatives are ordered from most-specific to least-specific so the colon form is tried
* before the bare uid, and BOOLEAN (FlexibleLiteralChoiceTerminal) comes last — its syntactic
* regex would otherwise greedily match tokens like "pick" or "identity" as boolean prefixes
* and short-circuit AlternativeCombinator.
*/
class ConfigParsePrivateUsersOptionValue : SimpleGrammarOptionValues(
"config_parse_private_users",
SequenceCombinator(
AlternativeCombinator(
// uid:range
SequenceCombinator(
IntegerTerminal(0, 4_294_967_296L),
LiteralChoiceTerminal(":"),
IntegerTerminal(0, 4_294_967_296L)
),
// bare uid
IntegerTerminal(0, 4_294_967_296L),
// string aliases
LiteralChoiceTerminal("pick", "identity"),
BOOLEAN
),
EOF()
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.*

/**
* Validator for RestrictNetworkInterfaces=.
*
* C function: config_parse_restrict_network_interfaces in src/core/load-fragment.c. Optional
* leading "~" (invert / denylist mode), followed by a whitespace-separated list of interface
* names that must pass ifname_valid_full(IFNAME_VALID_ALTERNATIVE):
* - 1..127 characters (ALTIFNAMSIZ - 1)
* - no whitespace, no '/', no ':', no '%' (rejected by ifname_valid_char)
* - cannot be "." or ".."
* - cannot be "all" or "default"
* - cannot be a purely-numeric string (interpreted as ifindex)
*
* The regex mirrors the existing config_parse_ifname validator but extends the length cap
* from 15 (IFNAMSIZ) to 127 (ALTIFNAMSIZ).
*/
class ConfigParseRestrictNetworkInterfacesOptionValue : SimpleGrammarOptionValues(
"config_parse_restrict_network_interfaces",
SequenceCombinator(
ZeroOrOne(LiteralChoiceTerminal("~")),
IFNAME,
ZeroOrMore(SequenceCombinator(WhitespaceTerminal(), IFNAME)),
EOF()
)
) {
companion object {
private val IFNAME = RegexTerminal(
"(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}",
"(?!(?:all|default|\\.{1,2}|0[xX][0-9a-fA-F]+|[0-9]+)\\Z)[^\\s:/%]{1,127}"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.*

/**
* Validator for EnvironmentFile=.
*
* C function: config_parse_unit_env_file in src/core/load-fragment.c. Each line is a single
* environment file path (after unit_path_printf specifier expansion); an optional leading "-"
* marks the file as missing-OK. The resolved path must be absolute (path_simplify_and_warn
* with PATH_CHECK_ABSOLUTE).
*/
class ConfigParseUnitEnvFileOptionValue : SimpleGrammarOptionValues(
"config_parse_unit_env_file",
SequenceCombinator(
ZeroOrOne(LiteralChoiceTerminal("-")),
RegexTerminal("/\\S*", "/\\S*"),
EOF()
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.ai

import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.SimpleGrammarOptionValues
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues.grammar.*

/**
* Validator for WorkingDirectory=.
*
* C function: config_parse_working_directory in src/core/load-fragment.c. Accepts:
* - optional leading "-" (missing path is non-fatal)
* - then either "~" alone (use the user's home) OR an absolute path
*
* Path values go through unit_path_printf so "%X" specifiers may appear inline. The grammar
* allows any non-whitespace characters in the path; tighter shell-metacharacter checks happen
* in path_simplify_and_warn at runtime.
*/
class ConfigParseWorkingDirectoryOptionValue : SimpleGrammarOptionValues(
"config_parse_working_directory",
SequenceCombinator(
ZeroOrOne(LiteralChoiceTerminal("-")),
AlternativeCombinator(
LiteralChoiceTerminal("~"),
RegexTerminal("/\\S*", "/\\S*")
),
EOF()
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai

import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest
import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection
import org.junit.Test

class ConfigParseBindNetworkInterfaceOptionValueTest : AbstractUnitFileTest() {

@Test
fun testValidValues() {
// language="unit file (systemd)"
val file = """
[Service]
BindNetworkInterface=eth0
BindNetworkInterface=lo
BindNetworkInterface=wlan0
BindNetworkInterface=br-1234abcd
""".trimIndent()

setupFileInEditor("file.service", file)
enableInspection(InvalidValueInspection::class.java)
val highlights = myFixture.doHighlighting()

assertSize(0, highlights)
}

@Test
fun testInvalidValues() {
// language="unit file (systemd)"
val file = """
[Service]
BindNetworkInterface=<error descr="Invalid value">all</error>
BindNetworkInterface=<error descr="Invalid value">default</error>
BindNetworkInterface=<error descr="Invalid value">eth0 eth1</error>
BindNetworkInterface=<error descr="Invalid value">eth0/0</error>
BindNetworkInterface=<error descr="Invalid value">123</error>
""".trimIndent()

setupFileInEditor("file.service", file)
enableInspection(InvalidValueInspection::class.java)
val highlights = myFixture.doHighlighting()

assertSize(5, highlights)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai

import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest
import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection
import org.junit.Test

class ConfigParseManagedOomRulesOptionValueTest : AbstractUnitFileTest() {

@Test
fun testValidValues() {
// language="unit file (systemd)"
val file = """
[Service]
OOMRules=default
OOMRules=default critical
OOMRules=rule1 rule2 rule3
OOMRules=my-rule_42
OOMRules=rule.with.dots
""".trimIndent()

setupFileInEditor("file.service", file)
enableInspection(InvalidValueInspection::class.java)
val highlights = myFixture.doHighlighting()

assertSize(0, highlights)
}

@Test
fun testInvalidValues() {
// language="unit file (systemd)"
val file = """
[Service]
OOMRules=<error descr="Invalid value">rule/with/slash</error>
OOMRules=<error descr="Invalid value">.</error>
OOMRules=<error descr="Invalid value">..</error>
OOMRules=<error descr="Invalid value">rule,other</error>
""".trimIndent()

setupFileInEditor("file.service", file)
enableInspection(InvalidValueInspection::class.java)
val highlights = myFixture.doHighlighting()

assertSize(4, highlights)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package net.sjrx.intellij.plugins.systemdunitfiles.inspections.ai

import net.sjrx.intellij.plugins.systemdunitfiles.AbstractUnitFileTest
import net.sjrx.intellij.plugins.systemdunitfiles.inspections.InvalidValueInspection
import org.junit.Test

class ConfigParsePrivateUsersOptionValueTest : AbstractUnitFileTest() {

@Test
fun testValidValues() {
// language="unit file (systemd)"
val file = """
[Exec]
PrivateUsers=yes
PrivateUsers=no
PrivateUsers=true
PrivateUsers=false
PrivateUsers=pick
PrivateUsers=identity
PrivateUsers=1000
PrivateUsers=0
PrivateUsers=1000:65536
PrivateUsers=100000:1000000
""".trimIndent()

setupFileInEditor("file.nspawn", file)
enableInspection(InvalidValueInspection::class.java)
val highlights = myFixture.doHighlighting()

assertSize(0, highlights)
}

@Test
fun testInvalidValues() {
// language="unit file (systemd)"
val file = """
[Exec]
PrivateUsers=<error descr="Invalid value">maybe</error>
PrivateUsers=<error descr="Invalid value">Pick</error>
PrivateUsers=<error descr="Invalid value">-1</error>
PrivateUsers=<error descr="Invalid value">1000:</error>
PrivateUsers=<error descr="Invalid value">:1000</error>
PrivateUsers=<error descr="Invalid value">1000 65536</error>
""".trimIndent()

setupFileInEditor("file.nspawn", file)
enableInspection(InvalidValueInspection::class.java)
val highlights = myFixture.doHighlighting()

assertSize(6, highlights)
}
}
Loading
Loading