Skip to content

Potential Enhancement CDS Utils library #219

@knewbury01

Description

@knewbury01

CAP is a fluent API and this informs our expectations of how it will be used. As such the following case is expected to be unrealisitic or rare:

function wrapperouter() {
    const temp = append
    wrapperinnermid(temp)
}

function wrapperinnermid(temp) {
    const a = temp('db/data') // sink
    wrapperinner(a)
}

function wrapperinner(a) {
    a.to('dist/db/data')  // sink - [FALSE_NEGATIVE] - rare case as CAP is a fluent API
}

cds.utils.append.to

direct usage is expected to be much more realistic and common

if this assumption is untrue, then the following addition to the CDSUtils.qll modelling may be made , which includes the use of type tracking to allow for detection of to calls that occur interprocedurally from the append calls

/**
 * CDS Utils:
 * `append`, `write`
 */
class FileWriters extends DataFlow::CallNode {
  FileWriters() {
    exists(CdsUtilsModuleAccess utils | utils.getMember(["append", "write"]).getACall() = this)
  }

  SourceNode fileReaderWriterUtils(TypeTracker t) {
    t.start() and
    result = this
    or
    exists(TypeTracker t2 | result = fileReaderWriterUtils(t2).track(t2, t))
  }

  SourceNode fileReaderWriterUtils() { result = fileReaderWriterUtils(TypeTracker::end()) }

  /**
   * Gets the arguments to these calls that represent data.
   */
  DataFlow::Node getData() {
    this.getNumArgument() = 1 and
    this.getArgument(0) = result
    or
    this.getNumArgument() = 2 and
    this.getArgument(1) = result
  }

  /**
   * Gets the arguments to these calls that represent a path.
   * Includes arguments to chained calls `to`, where that argument also represents a path.
   */
  DataFlow::Node getPath() {
    fileReaderWriterUtils().getAMemberCall("to").getAnArgument() = result
    or
    this.getNumArgument() = 2 and
    this.getArgument(0) = result
  }
}

/**
 * CDS Utils:
 * `copy`
 */
class FileReaderWriters extends DataFlow::CallNode {
  FileReaderWriters() {
    exists(CdsUtilsModuleAccess utils | utils.getMember(["copy"]).getACall() = this)
  }

  SourceNode fileReaderWriterUtils(TypeTracker t) {
    t.start() and
    result = this
    or
    exists(TypeTracker t2 | result = fileReaderWriterUtils(t2).track(t2, t))
  }

  SourceNode fileReaderWriterUtils() { result = fileReaderWriterUtils(TypeTracker::end()) }

  /**
   * Gets the arguments to these calls that represent a path.
   * Includes arguments to chained calls `to`, where that argument also represents a path.
   */
  DataFlow::Node getPath() {
    fileReaderWriterUtils().getAMemberCall("to").getArgument(_) = result
    or
    this.getAnArgument() = result
  }
}

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