void xdebug_xml_start_element_handler(void *ctx, const xmlChar *name, const xmlChar **atts)
{
	xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
	xdebug_xml_reader_priv *data = (xdebug_xml_reader_priv *) ctxt->_private;
	xdebug_xml_node *child;

	data->stack[data->level] = data->current;
	data->level++;

	child = xdebug_xml_node_init_ex(xdstrdup(name), 1);
	if (data->current) {
		xdebug_xml_add_child(data->current, child);
	}
	data->current = child;
	if (!data->xml) {
		data->xml = child;
	}
	
	if (atts) {
		do {
			xdebug_xml_add_attribute_ex(child, xdstrdup(atts[0]), xdstrdup(atts[1]), 1, 1);
			atts = &atts[2];
		} while (atts[0]);
	}
}
Exemple #2
0
// Exports the given xml key value pair as an xml child of the given parent node
static void xdebug_array_element_export_xml_node(xdebug_xml_node& parent,
                                                 const char* parentName,
                                                 const Variant& key,
                                                 const Variant& val,
                                                 XDebugExporter& exporter) {
  String key_str = key.toString();
  Variant full_name = init_null();

  // Construct the full name
  StringBuffer buf;
  if (parentName != nullptr)  {
    if (key.isInteger()) {
      buf.printf("%s[%s]", parentName, key_str.data());
    } else {
      buf.printf("%s['%s']", parentName, key_str.data());
    }
    full_name = buf.detach();
  }
  const char* full_name_str = full_name.isNull() ?
    nullptr : full_name.toString().data();

  // Recursively add the child
  xdebug_xml_node* child = xdebug_var_export_xml_node(xdstrdup(key_str.data()),
                                                      xdstrdup(full_name_str),
                                                      nullptr,
                                                      val, exporter);
  xdebug_xml_add_child(&parent, child);
}
Exemple #3
0
xdebug_xml_node* xdebug_get_value_xml_node(const char* name,
                                           const Variant& val,
                                           XDebugVarType type
                                            /* = XDebugVarType::Normal */,
                                           XDebugExporter& exporter) {
  // Compute the short and full name of the passed value
  char* short_name = nullptr;
  char* full_name = nullptr;
  if (name) {
    switch (type) {
      case XDebugVarType::Normal: {
        char* tmp_name = prepare_variable_name(name);
        short_name = xdstrdup(tmp_name);
        full_name = xdstrdup(tmp_name);
        xdfree(tmp_name);
        break;
      }
      case XDebugVarType::Static:
        short_name = xdebug_sprintf("::%s", name);
        full_name =  xdebug_sprintf("::%s", name);
        break;
      case XDebugVarType::Constant:
        short_name = xdstrdup(name);
        full_name =  xdstrdup(name);
        break;
      default:
        throw Exception("Invalid variable type");
    }
  }

  // Recursively construct the xml
  return xdebug_var_export_xml_node(short_name, full_name, nullptr,
                                    val, exporter);
}
Exemple #4
0
static xdebug_monitored_function_entry *xdebug_monitored_function_init(char *func_name, char *filename, int lineno)
{
	xdebug_monitored_function_entry *tmp = xdmalloc(sizeof(xdebug_monitored_function_dtor));

	tmp->func_name = xdstrdup(func_name);
	tmp->filename = xdstrdup(filename);
	tmp->lineno = lineno;

	return tmp;
}
Exemple #5
0
char *xdebug_sprintf(const char* fmt, ...)
{
	char   *new_str;
	int     size = 1;
	va_list args;
	char   *orig_locale;

	orig_locale = xdstrdup(setlocale(LC_ALL, NULL));
	setlocale(LC_ALL, "C");
	new_str = (char *) xdmalloc(size);

	for (;;) {
		int n;

		va_start(args, fmt);
		n = vsnprintf(new_str, size, fmt, args);
		va_end(args);

		if (n > -1 && n < size) {
			break;
		}
		if (n < 0) {
			size *= 2;
		} else {
			size = n + 1;
		}
		new_str = (char *) xdrealloc(new_str, size);
	}
	setlocale(LC_ALL, orig_locale);
	xdfree(orig_locale);

	return new_str;
}
Exemple #6
0
// TODO(#3704) Clean this up-- this was taken from php5 xdebug
char* XDebugUtils::pathToUrl(const char* fileurl) {
  int l, i, new_len;
  char *tmp = nullptr;
  char *encoded_fileurl;

  /* encode the url */
  encoded_fileurl = xdebug_raw_url_encode(fileurl, strlen(fileurl),
                                          &new_len, 1);

  if (strncmp(fileurl, "phar://", 7) == 0) {
    /* ignore, phar is cool */
    tmp = xdstrdup(fileurl);
  } else if (fileurl[0] != '/' && fileurl[0] != '\\' && fileurl[1] != ':') {
    String path(fileurl, CopyString);
    Variant realpath = HHVM_FN(realpath)(path);
    if (realpath.isString()) {
      char* realpath_str = realpath.toString().get()->mutableData();
      tmp = xdebug_sprintf("file://%s", realpath_str);
    } else {
      // Couldn't convert, use raw path
      tmp = xdstrdup(encoded_fileurl);
    }
  } else if (fileurl[1] == '/' || fileurl[1] == '\\') {
    // convert UNC paths (eg. \\server\sharepath)
    // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx
    tmp = xdebug_sprintf("file:%s", encoded_fileurl);
  } else if (fileurl[0] == '/' || fileurl[0] == '\\') {
    /* convert *nix paths (eg. /path) */
    tmp = xdebug_sprintf("file://%s", encoded_fileurl);
  } else if (fileurl[1] == ':') {
    /* convert windows drive paths (eg. c:\path) */
    tmp = xdebug_sprintf("file:///%s", encoded_fileurl);
  } else {
    /* no clue about it, use it raw */
    tmp = xdstrdup(encoded_fileurl);
  }
  l = strlen(tmp);
  /* convert '\' to '/' */
  for (i = 0; i < l; i++) {
    if (tmp[i] == '\\') {
      tmp[i]='/';
    }
  }
  xdfree(encoded_fileurl); // Needs to be free
  return tmp;
}
Exemple #7
0
void xdebug_xml_add_attribute_dup(
  xdebug_xml_node* xml,
  const char* attr,
  const char* val
) {
  // const-cast is okay since we are not freeing the passed attribute.
  auto const cattr = const_cast<char*>(attr);
  xdebug_xml_add_attribute_ex(xml, cattr, xdstrdup(val), 0, 1);
}
xdebug_coverage_function *xdebug_coverage_function_ctor(char *function_name)
{
	xdebug_coverage_function *function;

	function = xdmalloc(sizeof(xdebug_coverage_function));
	function->name = xdstrdup(function_name);
	function->branch_info = NULL;

	return function;
}
void xdebug_xml_char_handler(void *ctx, const xmlChar *ch, int len)
{
	xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
	xdebug_xml_reader_priv *data = (xdebug_xml_reader_priv *) ctxt->_private;
	char *tmp;

	tmp = strndup(ch, len);
	xdebug_xml_add_text(data->current, xdstrdup(tmp));
	free(tmp);
}
Exemple #10
0
static void init_function_monitor_hash(xdebug_hash *internal, HashTable *functions_to_monitor)
{
	zval *val;

	ZEND_HASH_FOREACH_VAL(functions_to_monitor, val) {
		if (Z_TYPE_P(val) == IS_STRING) {
			xdebug_hash_add(internal, Z_STRVAL_P(val), Z_STRLEN_P(val), xdstrdup(Z_STRVAL_P(val)));
		}
	} ZEND_HASH_FOREACH_END();
}
Exemple #11
0
void xdebug_log_stack(const char *error_type_str, char *buffer, const char *error_filename, const int error_lineno TSRMLS_DC)
{
	xdebug_llist_element *le;
	function_stack_entry *i;
	char                 *tmp_log_message;

	tmp_log_message = xdebug_sprintf( "PHP %s:  %s in %s on line %d", error_type_str, buffer, error_filename, error_lineno);
	php_log_err(tmp_log_message TSRMLS_CC);
	xdfree(tmp_log_message);

	if (XG(stack) && XG(stack)->size) {
		php_log_err("PHP Stack trace:" TSRMLS_CC);

		for (le = XDEBUG_LLIST_HEAD(XG(stack)); le != NULL; le = XDEBUG_LLIST_NEXT(le))
		{
			int c = 0; /* Comma flag */
			int j = 0; /* Counter */
			char *tmp_name;
			xdebug_str log_buffer = {0, 0, NULL};

			i = XDEBUG_LLIST_VALP(le);
			tmp_name = xdebug_show_fname(i->function, 0, 0 TSRMLS_CC);
			xdebug_str_add(&log_buffer, xdebug_sprintf("PHP %3d. %s(", i->level, tmp_name), 1);
			xdfree(tmp_name);

			/* Printing vars */
			for (j = 0; j < i->varc; j++) {
				char *tmp_varname, *tmp_value;

				if (c) {
					xdebug_str_addl(&log_buffer, ", ", 2, 0);
				} else {
					c = 1;
				}
				tmp_varname = i->var[j].name ? xdebug_sprintf("$%s = ", i->var[j].name) : xdstrdup("");
				xdebug_str_add(&log_buffer, tmp_varname, 0);
				xdfree(tmp_varname);

				if (i->var[j].addr) {
					tmp_value = xdebug_get_zval_value(i->var[j].addr, 0, NULL);
					xdebug_str_add(&log_buffer, tmp_value, 0);
					xdfree(tmp_value);
				} else {
					xdebug_str_addl(&log_buffer, "*uninitialized*", 15, 0);
				}
			}

			xdebug_str_add(&log_buffer, xdebug_sprintf(") %s:%d", i->filename, i->lineno), 1);
			php_log_err(log_buffer.d TSRMLS_CC);
			xdebug_str_free(&log_buffer);
		}
	}
}
xdebug_coverage_file *xdebug_coverage_file_ctor(char *filename)
{
	xdebug_coverage_file *file;

	file = xdmalloc(sizeof(xdebug_coverage_file));
	file->name = xdstrdup(filename);
	file->lines = xdebug_hash_alloc(128, xdebug_coverage_line_dtor);
	file->functions = xdebug_hash_alloc(128, xdebug_coverage_function_dtor);
	file->has_branch_info = 0;

	return file;
}
Exemple #13
0
static void init_function_monitor_hash(xdebug_hash *internal, HashTable *functions_to_monitor)
{
	HashPosition  pos;
	zval        **val;

	zend_hash_internal_pointer_reset_ex(functions_to_monitor, &pos);
	while (zend_hash_get_current_data_ex(functions_to_monitor, (void **) &val, &pos) != FAILURE) {
		if (Z_TYPE_PP(val) == IS_STRING) {
			xdebug_hash_add(internal, Z_STRVAL_PP(val), Z_STRLEN_PP(val), xdstrdup(Z_STRVAL_PP(val)));
		}

		zend_hash_move_forward_ex(functions_to_monitor, &pos);
	}
}
Exemple #14
0
char* xdebug_error_type(int type)
{
	switch (type) {
		case E_ERROR:
		case E_CORE_ERROR:
		case E_COMPILE_ERROR:
		case E_USER_ERROR:
			return xdstrdup("Fatal error");
			break;
#if PHP_VERSION_ID >= 50200
		case E_RECOVERABLE_ERROR:
			return xdstrdup("Catchable fatal error");
			break;
#endif
		case E_WARNING:
		case E_CORE_WARNING:
		case E_COMPILE_WARNING:
		case E_USER_WARNING:
			return xdstrdup("Warning");
			break;
		case E_PARSE:
			return xdstrdup("Parse error");
			break;
		case E_NOTICE:
		case E_USER_NOTICE:
			return xdstrdup("Notice");
			break;
		case E_STRICT:
			return xdstrdup("Strict standards");
			break;
#if PHP_VERSION_ID >= 50300
		case E_DEPRECATED:
			return xdstrdup("Deprecated");
			break;
#endif
		default:
			return xdstrdup("Unknown error");
			break;
	}
}
Exemple #15
0
char* xdebug_return_trace_assignment(function_stack_entry *i, char *varname, zval *retval, char *op, char *filename, int lineno TSRMLS_DC)
{
	int        j = 0;
	xdebug_str str = {0, 0, NULL};
	char      *tmp_value;

	if (XG(trace_format) != 0) {
		return xdstrdup("");
	}

	xdebug_str_addl(&str, "                    ", 20, 0);
	if (XG(show_mem_delta)) {
		xdebug_str_addl(&str, "        ", 8, 0);
	}
	for (j = 0; j <= i->level; j++) {
		xdebug_str_addl(&str, "  ", 2, 0);
	}
	xdebug_str_addl(&str, "   => ", 6, 0);

	xdebug_str_add(&str, varname, 0);

	if (op[0] != '\0' ) { /* pre/post inc/dec ops are special */
		xdebug_str_add(&str, xdebug_sprintf(" %s ", op), 1);

		tmp_value = xdebug_get_zval_value(retval, 0, NULL);

		if (tmp_value) {
			xdebug_str_add(&str, tmp_value, 1);
		} else {
			xdebug_str_addl(&str, "NULL", 4, 0);
		}
	}
	xdebug_str_add(&str, xdebug_sprintf(" %s:%d\n", filename, lineno), 1);

	return str.d;
}
Exemple #16
0
static void xdebug_object_element_export_xml_node(xdebug_xml_node& parent,
                                                  const char* parentName,
                                                  const ObjectData* obj,
                                                  const Variant& key,
                                                  const Variant& val,
                                                  XDebugExporter& exporter) {
  auto const prop_str = key.toString();
  auto const cls = obj->getVMClass();
  auto const cls_name = cls->name()->data();

  // Compute whether the properity is static.

  auto const sLookup = cls->getSProp(nullptr, prop_str.get());

  auto const is_static = sLookup.prop != nullptr;
  bool visible = is_static;
  bool accessible = sLookup.accessible;

  // If the property is not static, we know it's a member, but need to grab the
  // visibility
  if (!is_static) {
    bool unset;
    obj->getProp(nullptr, prop_str.get(), visible, accessible, unset);
  }

  // This is public if it is visible and accessible from the nullptr context
  bool is_public = visible && accessible;

  // Compute the property name and full name
  const char* name;
  const char* full_name = nullptr;
  if (!val.isInteger()) {
    // Compute the property name
    if (is_public) {
      name = xdstrdup(prop_str.data());
    } else {
      name = xdebug_sprintf("*%s*%s", cls_name, prop_str.data());
    }

    // Compute the property full name if we have a parent name
    if (parentName != nullptr) {
      if (is_public && is_static) {
        full_name = xdebug_sprintf("%s::%s", parentName, prop_str.data());
      } else if (is_public && !is_static) {
        full_name = xdebug_sprintf("%s->%s", parentName, prop_str.data());
      } else if (!is_public && is_static) {
        full_name = xdebug_sprintf("%s::*%s*%s", parentName, "::",
                                   cls_name, prop_str.data());
      } else if (!is_public && !is_static) {
        full_name = xdebug_sprintf("%s->*%s*%s", parentName, "->",
                                   cls_name, prop_str.data());
      }
    }
  } else {
    // Compute the name + full name if we have a parent name
    name = xdebug_sprintf("%ld", key.toInt64());
    if (parentName != nullptr) {
      if (is_static) {
        full_name = xdebug_sprintf("%s::%ld", parentName, key.toInt64());
      } else {
        full_name = xdebug_sprintf("%s->%ld", parentName, key.toInt64());
      }
    }
  }

  // Compute the facet (static/non-static + public/private)
  const char* facet = xdebug_sprintf("%s%s",
                                     is_static ? "static " : "",
                                     is_public ? "public" : "private");

  // Recursively write the this property. The duplications are necessary due to
  // the xdebug xml api
  xdebug_xml_node* child = xdebug_var_export_xml_node(xdstrdup(name),
                                                      xdstrdup(full_name),
                                                      xdstrdup(facet),
                                                      val, exporter);
  xdebug_xml_add_child(&parent, child);
}
Exemple #17
0
xdebug_xml_node* xdebug_var_export_xml_node(const char* name,
                                            const char* fullName,
                                            const char* facet,
                                            const Variant& var,
                                            XDebugExporter& exporter) {
  // Setup the node. Each const cast is necessary due to xml api
  xdebug_xml_node* node = xdebug_xml_node_init("property");
  if (name != nullptr) {
    xdebug_xml_add_attribute_ex(node, "name", const_cast<char*>(name), 0, 1);
  }
  if (fullName != nullptr) {
    xdebug_xml_add_attribute_ex(node, "fullname", const_cast<char*>(fullName),
                                0, 1);
  }
  if (facet != nullptr) {
    xdebug_xml_add_attribute_ex(node, "facet", const_cast<char*>(facet), 0, 1);
  }
  xdebug_xml_add_attribute_ex(node, "address",
                              xdebug_sprintf("%ld", (long) &var), 0, 1);

  // Case on the type for the rest
  if (var.isBoolean()) {
    xdebug_xml_add_attribute(node, "type", "bool");
    xdebug_xml_add_text(node, xdebug_sprintf("%d",  var.toBoolean()));
  } else if (var.isNull()) {
    xdebug_xml_add_attribute(node, "type", "null");
  } else if (var.isInteger()) {
    xdebug_xml_add_attribute(node, "type", "int");
    xdebug_xml_add_text(node, xdebug_sprintf("%ld", var.toInt64()));
  } else if (var.isDouble()) {
    xdebug_xml_add_attribute(node, "type", "float");
    xdebug_xml_add_text(node, xdebug_sprintf("%lG", var.toDouble()));
  } else if (var.isString()) {
    // Add the type and the original size
    String str = var.toString();
    xdebug_xml_add_attribute(node, "type", "string");
    xdebug_xml_add_attribute_ex(node, "size",
                                xdebug_sprintf("%d", str.size()), 0, 1);

    // Possibly shrink the string, then add it to the node
    if (exporter.max_data != 0 && str.size() > exporter.max_data) {
      str = str.substr(0, exporter.max_data);
    }
    xdebug_xml_add_text_encodel(node, xdstrdup(str.data()), str.size());
  } else if (var.isArray()) {
    Array arr = var.toArray();
    xdebug_xml_add_attribute(node, "type", "array");
    xdebug_xml_add_attribute(node, "children",
                             const_cast<char*>(arr.size() > 0 ? "1" : "0"));

    // If we've already seen this object, return
    if (exporter.counts[arr.get()]++ > 0) {
      xdebug_xml_add_attribute(node, "recursive", "1");
      return node;
    }

    // Write the # of children then short-circuit if we are too deep
    xdebug_xml_add_attribute_ex(node, "numchildren",
                                xdebug_sprintf("%d", arr.size()), 0, 1);
    if (exporter.level++ >= exporter.max_depth) {
      return node;
    }

    // Compute the page and the start/end indices
    // Note that php xdebug doesn't support pages except for at the top level
    uint32_t page = exporter.level == 1 ? exporter.page : 0;
    uint32_t start = page * exporter.max_children;
    uint32_t end = (page + 1) * exporter.max_children;
    xdebug_xml_add_attribute_ex(node, "page", xdebug_sprintf("%d", page), 0, 1);
    xdebug_xml_add_attribute_ex(node, "pagesize",
                                xdebug_sprintf("%d", exporter.max_children),
                                0, 1);
    // Add each child
    ArrayIter iter(arr);
    iter.setPos(start);
    for (uint32_t i = start; i < end && iter; i++, ++iter) {
      xdebug_array_element_export_xml_node(*node, name,
                                           iter.first(),
                                           iter.second(),
                                           exporter);
    }

    // Done at this level
    exporter.level--;
    exporter.counts[arr.get()]--;
  } else if (var.isObject()) {
    // TODO(#3704) This could be merged into the above array code. For now,
    // it's separate as this was pulled originally from xdebug
    ObjectData* obj = var.toObject().get();
    Class* cls = obj->getVMClass();
    Array props = get_object_props(obj);

    // Add object info
    xdebug_xml_add_attribute(node, "type", "object");
    xdebug_xml_add_attribute_ex(node, "classname",
                                xdstrdup(cls->name()->data()), 0, 1);
    xdebug_xml_add_attribute(node, "children",
                             const_cast<char*>(props.size() ? "1" : "0"));

    // If we've already seen this object, return
    if (exporter.counts[obj]++ > 0) {
      xdebug_xml_add_attribute(node, "recursive", "1");
      return node;
    }

    // Add the # of props then short circuit if we are too deep
    xdebug_xml_add_attribute_ex(node, "numchildren",
                                xdebug_sprintf("%d", props.size()), 0, 1);
    if (exporter.level++ >= exporter.max_depth) {
      return node;
    }

    // Compute the page and the start/end indices
    // Note that php xdebug doesn't support pages except for at the top level
    uint32_t page = exporter.level == 1 ? exporter.page : 0;
    uint32_t start = page * exporter.max_children;
    uint32_t end = (page + 1) * exporter.max_children;
    xdebug_xml_add_attribute_ex(node, "page", xdebug_sprintf("%d", page), 0, 1);
    xdebug_xml_add_attribute_ex(node, "pagesize",
                                xdebug_sprintf("%d", exporter.max_children),
                                0, 1);

    // Add each property
    ArrayIter iter(props);
    iter.setPos(start);
    for (uint32_t i = start; i < end && iter; i++, ++iter) {
      xdebug_object_element_export_xml_node(*node, name, obj,
                                            iter.first(),
                                            iter.second(),
                                            exporter);
    }

    // Done at this level
    exporter.level--;
    exporter.counts[(void*) obj]--;
  } else if (var.isResource()) {
    ResourceData* res = var.toResource().get();
    xdebug_xml_add_attribute(node, "type", "resource");
    const char* text = xdebug_sprintf("resource id='%ld' type='%s'",
                                      res->o_getId(),
                                      res->o_getResourceName().data());
    xdebug_xml_add_text(node, const_cast<char*>(text));
  } else {
    xdebug_xml_add_attribute(node, "type", "null");
  }
  return node;
}