Esempio n. 1
0
TypedValue HHVM_FUNCTION(dummy_arraylike_builtin, const Variant& var) {
  if (var.isArray()) {
    auto const& arr = var.asCArrRef();
    return tvReturn(arr);
  }
  return tvReturn(staticEmptyKeysetArray());
}
Esempio n. 2
0
TypedValue HHVM_FUNCTION(dummy_varr_or_darr_builtin, const Variant& var) {
  if (var.isArray()) {
    auto const& arr = var.asCArrRef();
    if (arr.isVecOrVArray() || arr.isDictOrDArray()) return tvReturn(arr);
  }
  return tvReturn(staticEmptyVArray());
}
Esempio n. 3
0
TypedValue HHVM_FUNCTION(serialize_memoize_param, TypedValue param) {
  // Memoize throws in the emitter if any function parameters are references, so
  // we can just assert that the param is cell here
  assertx(param.m_type != KindOfRef);
  auto const type = param.m_type;

  if (isStringType(type)) {
    auto const str = param.m_data.pstr;
    if (str->empty()) {
      return make_tv<KindOfPersistentString>(s_emptyStrMemoKey.get());
    } else if ((unsigned char)str->data()[0] < '~') {
      // fb_compact_serialize always returns a string with the high-bit set in
      // the first character. Furthermore, we use ~ to begin all our special
      // constants, so anything less than ~ can't collide. There's no worry
      // about int-like strings because we use dicts (which don't perform key
      // coercion) to store the memoized values.
      str->incRefCount();
      return param;
    }
  } else if (isContainer(param) && getContainerSize(param) == 0) {
    return make_tv<KindOfPersistentString>(s_emptyArrMemoKey.get());
  } else if (type == KindOfUninit || type == KindOfNull) {
    return make_tv<KindOfPersistentString>(s_nullMemoKey.get());
  } else if (type == KindOfBoolean) {
    return make_tv<KindOfPersistentString>(
      param.m_data.num ? s_trueMemoKey.get() : s_falseMemoKey.get()
    );
  } else if (type == KindOfInt64) {
    return param;
  }

  return tvReturn(
    fb_compact_serialize(tvAsCVarRef(&param),
                         FBCompactSerializeBehavior::MemoizeParam));
}
Esempio n. 4
0
TypedValue HHVM_FUNCTION(preg_match,
                         StringArg pattern, StringArg subject,
                         OutputArg matches /* = null */,
                         int flags /* = 0 */, int offset /* = 0 */) {
  return tvReturn(preg_match(StrNR(pattern.get()), StrNR(subject.get()),
                             matches.get() ? matches->var() : nullptr,
                             flags, offset));
}
Esempio n. 5
0
TypedValue HHVM_FUNCTION(preg_match_all,
                         const String& pattern,
                         const String& subject,
                         OutputArg matches /* = null */,
                         int flags /* = 0 */,
                         int offset /* = 0 */) {
  return tvReturn(preg_match_all(pattern, subject,
                                 matches.get() ? matches->var() : nullptr,
                                 flags, offset));
}
Esempio n. 6
0
TypedValue HHVM_FUNCTION(json_encode, const Variant& value,
                         int64_t options, int64_t depth) {
  // Special case for resource since VariableSerializer does not take care of it
  if (value.isResource()) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_UNSUPPORTED_TYPE);
    return tvReturn(json_guard_error_result("null", options));
  }

  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
  VariableSerializer vs(VariableSerializer::Type::JSON, options);
  vs.setDepthLimit(depth);

  String json = vs.serializeValue(value, !(options & k_JSON_FB_UNLIMITED));
  assertx(json.get() != nullptr);
  if (UNLIKELY(StructuredLog::coinflip(RuntimeOption::EvalSerDesSampleRate))) {
    StructuredLog::logSerDes("json", "ser", json, value);
  }

  if (json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE) {
    return tvReturn(json_guard_error_result(json, options));
  }

  return tvReturn(std::move(json));
}
Esempio n. 7
0
TypedValue HHVM_FUNCTION(json_decode, const String& json,
                         bool assoc, int64_t depth, int64_t options) {
  json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

  if (json.empty()) {
    return make_tv<KindOfNull>();
  }

  const int64_t supported_options =
    k_JSON_FB_LOOSE |
    k_JSON_FB_COLLECTIONS |
    k_JSON_FB_STABLE_MAPS |
    k_JSON_BIGINT_AS_STRING |
    k_JSON_FB_HACK_ARRAYS;
  int64_t parser_options = options & supported_options;
  Variant z;
  const auto ok =
    JSON_parser(z, json.data(), json.size(), assoc, depth, parser_options);
  if (UNLIKELY(StructuredLog::coinflip(RuntimeOption::EvalSerDesSampleRate))) {
    StructuredLog::logSerDes("json", "des", json, z);
  }
  if (ok) {
    return tvReturn(std::move(z));
  }

  String trimmed = HHVM_FN(trim)(json, "\t\n\r ");

  if (trimmed.size() == 4) {
    if (!strcasecmp(trimmed.data(), "null")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return make_tv<KindOfNull>();
    }
    if (!strcasecmp(trimmed.data(), "true")) {
      json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
      return make_tv<KindOfBoolean>(true);
    }
  } else if (trimmed.size() == 5 && !strcasecmp(trimmed.data(), "false")) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return make_tv<KindOfBoolean>(false);
  }

  int64_t p;
  double d;
  DataType type = json.get()->isNumericWithVal(p, d, 0);
  if (type == KindOfInt64) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return make_tv<KindOfInt64>(p);
  } else if (type == KindOfDouble) {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    if ((options & k_JSON_BIGINT_AS_STRING) &&
        (json.toInt64() == LLONG_MAX || json.toInt64() == LLONG_MIN)
        && errno == ERANGE) { // Overflow
      bool is_float = false;
      for (int i = (trimmed[0] == '-' ? 1 : 0); i < trimmed.size(); ++i) {
        if (trimmed[i] < '0' || trimmed[i] > '9') {
          is_float = true;
          break;
        }
      }
      if (!is_float) {
        return tvReturn(trimmed);
      }
    }
    return make_tv<KindOfDouble>(d);
  }

  char ch0 = json.charAt(0);
  if (json.size() > 1 && ch0 == '"' && json.charAt(json.size() - 1) == '"') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);

    // Wrap the string in an array to allow the JSON_parser to handle
    // things like unicode escape sequences, then unwrap to get result
    String wrapped("[");
    wrapped += json + "]";
    // Stick to a normal hhvm array for the wrapper
    const int64_t mask = ~(k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS);
    if (JSON_parser(z, wrapped.data(), wrapped.size(), false, depth,
                    parser_options & mask) && z.isArray()) {
      Array arr = z.toArray();
      if ((arr.size() == 1) && arr.exists(0)) {
        return tvReturn(arr[0]);
      }
      // The input string could be something like: "foo","bar"
      // Which will parse inside the [] wrapper, but be invalid
      json_set_last_error_code(json_error_codes::JSON_ERROR_SYNTAX);
    }
  }

  if ((options & k_JSON_FB_LOOSE) && json.size() > 1 &&
      ch0 == '\'' && json.charAt(json.size() - 1) == '\'') {
    json_set_last_error_code(json_error_codes::JSON_ERROR_NONE);
    return tvReturn(json.substr(1, json.size() - 2));
  }

  assert(json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE);
  return make_tv<KindOfNull>();
}
Esempio n. 8
0
TypedValue HHVM_FUNCTION(launder_value, const Variant& val) {
  return tvReturn(val);
}