Skip to content

PcmlProgram: hard-coded 7-parameter limit ignores VRM (248 supported on 7.3+) #335

Description

@igor-sajtlava

Description

In JTOpen, PcmlProgram.callProgram() enforces a hard-coded limit of 7 or fewer parameters for service program (*SRVPGM) calls, regardless of the target IBM i system's version/release/modification (VRM). This limit is stale: on IBM i 7.3 and 7.4 (with PTFs SI75449/SI75397) and later releases, QZRUCLSP supports up to 248 parameters.

As a result, PCML-based service program calls fail with a TOO_MANY_PARMS exception when 8–248 parameters are defined, even though the underlying system fully supports them. The correct, VRM-aware approach already exists in ServiceProgramCall.run() and should be mirrored in PcmlProgram.

Steps to Reproduce

  1. Target an IBM i system at VRM > 7.2 (e.g., 7.3 with the required PTFs, 7.4, or 7.5).
  2. Define a PCML document with a <program> element pointing to a *SRVPGM with an entrypoint, declaring more than 7 parameters (e.g., 10).
  3. Invoke the program via ProgramCallDocument.callProgram().
  4. The call fails before it is ever sent to the system.

Expected Behavior

For systems at VRM > 7.2, PcmlProgram should allow up to 248 parameters for service program calls. When more than 7 parameters are used, each parameter must be passed by reference (pointer) — matching the rule enforced in ServiceProgramCall.

Actual Behavior

PcmlProgram unconditionally rejects any service program call with more than 7 parameters, throwing:

PcmlException (DAMRI.TOO_MANY_PARMS)

Root Cause Analysis

File: com/ibm/as400/data/PcmlProgram.java
Method: callProgram()
Lines: ~519–525

The parameter-count check is hard-coded to 7 and does not consider the host VRM:

// Service programs can only have 7 or fewer parameters (this is a server limitation).
// Note: This check does not take into account that minvrm= and maxvrm=
//       can reduce the number of parameters at runtime
if ( getNbrChildren() > 7 )                             // @D1A
{
    throw new PcmlException(DAMRI.TOO_MANY_PARMS, new Object[] {makeQuotedAttr("entrypoint", m_EntrypointStr), Integer.valueOf(7), getBracketedTagName(), getNameForException()} ); // @D1A
}

By contrast, ServiceProgramCall.run() (lines ~307–332) already implements the correct, VRM-aware logic:

//@AE2 For 7.4 and 7.3, QZRUCLSP PTF SI75449 and SI75397 supports 248 parameters.
if (system_.getVRM() > 0x00070200) {
    if (parameterList_.length > 248) {
        Trace.log(Trace.ERROR, "Parameter list length exceeds limit of 248 parameters:", parameterList_.length);
        throw new ExtendedIllegalArgumentException("parameterList.length (" + parameterList_.length + ")", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
    }
    if (parameterList_.length > 7) {
        for (int i = 0; i < parameterList_.length; ++i) {
            int parameterType = parameterList_[i].getParameterType();
            if (parameterType != 2) { // must be pass-by-reference (pointer)
                Trace.log(Trace.ERROR, "Parameter list length is larger than 7 parameters, all parameters must be passed as pointers. The parameter ", i);
                throw new ExtendedIllegalArgumentException("The parameter [" + i + "]", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
            }
        }
    }
} else {
    if (parameterList_.length > 7) {
        Trace.log(Trace.ERROR, "Parameter list length exceeds limit of 7 parameters:", parameterList_.length);
        throw new ExtendedIllegalArgumentException("parameterList.length (" + parameterList_.length + ")", ExtendedIllegalArgumentException.PARAMETER_VALUE_NOT_VALID);
    }
}

PcmlProgram has access to the system object (as400, used a few lines later at as400.getCcsid()), so the host VRM is readily available via as400.getVRM().

Proposed Fix

Replace the hard-coded > 7 check in PcmlProgram.callProgram() with the same VRM-aware logic used in ServiceProgramCall.run():

  • If host VRM > 0x00070200: allow up to 248 parameters; when more than 7, require every parameter to be passed by reference (pointer). Otherwise throw TOO_MANY_PARMS.
  • If host VRM ≤ 0x00070200: keep the existing 7-parameter limit.
if ( getPath().toUpperCase().endsWith(".SRVPGM") )
{
    if (getEntrypoint() == null)
    {
        throw new PcmlException(DAMRI.NO_ENTRYPOINT, new Object[] {makeQuotedAttr("entrypoint", m_EntrypointStr), getBracketedTagName(), getNameForException()} );
    }

    // For 7.3/7.4 (QZRUCLSP PTF SI75449/SI75397) and later, up to 248 parameters are supported.
    // When more than 7 parameters are used, all must be passed by reference (pointer).
    if (as400.getVRM() > 0x00070200)
    {
        if ( getNbrChildren() > 248 )
        {
            throw new PcmlException(DAMRI.TOO_MANY_PARMS, new Object[] {makeQuotedAttr("entrypoint", m_EntrypointStr), Integer.valueOf(248), getBracketedTagName(), getNameForException()} );
        }
        // (When >7 parameters, validate that each child parameter is passed by reference,
        //  mirroring ServiceProgramCall's pointer-type check.)
    }
    else if ( getNbrChildren() > 7 )
    {
        throw new PcmlException(DAMRI.TOO_MANY_PARMS, new Object[] {makeQuotedAttr("entrypoint", m_EntrypointStr), Integer.valueOf(7), getBracketedTagName(), getNameForException()} );
    }
}

Why this is safe:

Scenario Behavior
VRM ≤ 7.2, ≤ 7 parameters Allowed (unchanged)
VRM ≤ 7.2, > 7 parameters TOO_MANY_PARMS with limit 7 (unchanged)
VRM > 7.2, ≤ 7 parameters Allowed (unchanged)
VRM > 7.2, 8–248 parameters (all by reference) Allowed (newly enabled, matches ServiceProgramCall)
VRM > 7.2, > 248 parameters TOO_MANY_PARMS with limit 248

Versions

  • Affected: all versions where PcmlProgram retains the hard-coded 7-parameter limit (@D1A).
  • Reference implementation: ServiceProgramCall (@AE2) already handles this correctly.

Environment

  • IBM i (AS/400) target system at VRM > 7.2 (7.3 with SI75449/SI75397, 7.4, 7.5)
  • Service program (*SRVPGM) calls via PCML (ProgramCallDocument)
  • Java 8+ runtime

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions