Code:  void WebPageSerializerImpl::openTagToString(Element* element,
                                             SerializeDomParam* param)
 {
    bool needSkip;
    StringBuilder result;
    result.append(preActionBeforeSerializeOpenTag(element, param, &needSkip));
    if (needSkip)
        return;
    result.append('<');
    result.append(element->nodeName().lower());
    AttributeCollection attributes = element->attributes();
    AttributeCollection::iterator end = attributes.end();
    for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
        result.append(' ');
        result.append(it->name().toString());
        result.appendLiteral("=\"");
        if (!it->value().isEmpty()) {
            const String& attrValue = it->value();

            const QualifiedName& attrName = it->name();
             if (element->hasLegalLinkAttribute(attrName)) {
                 if (attrValue.startsWith("javascript:", TextCaseInsensitive)) {
                    result.append(attrValue);
                 } else {
                     WebLocalFrameImpl* subFrame = WebLocalFrameImpl::fromFrameOwnerElement(element);
                    String completeURL = subFrame ? subFrame->frame()->document()->url() :
                                                    param->document->completeURL(attrValue);
                    if (m_localLinks.contains(completeURL)) {
                        if (!param->directoryName.isEmpty()) {
                            result.appendLiteral("./");
                             result.append(param->directoryName);
                             result.append('/');
                         }
                        result.append(m_localLinks.get(completeURL));
                     } else {
                        result.append(completeURL);
                     }
                 }
             } else {
                if (param->isHTMLDocument)
                    result.append(m_htmlEntities.convertEntitiesInString(attrValue));
                else
                    result.append(m_xmlEntities.convertEntitiesInString(attrValue));
            }
        }
        result.append('\"');
    }

    String addedContents = postActionAfterSerializeOpenTag(element, param);
    if (element->hasChildren() || param->haveAddedContentsBeforeEnd)
        result.append('>');
    result.append(addedContents);
    saveHTMLContentToBuffer(result.toString(), param);
}

Vulnerability Type: 
CWE ID: CWE-20
Summary: The WebPageSerializerImpl::openTagToString function in WebKit/Source/web/WebPageSerializerImpl.cpp in the page serializer in Google Chrome before 47.0.2526.80 does not properly use HTML entities, which might allow remote attackers to inject arbitrary web script or HTML via a crafted document, as demonstrated by a double-quote character inside a single-quoted string.
Commit Message: Make WebPageSerializerImpl to escape URL attribute values in result.

This patch makes |WebPageSerializerImpl| to escape URL attribute values rather
than directly output URL attribute values into result.

BUG=542054
TEST=webkit_unit_tests --gtest_filter=WebPageSerializerTest.URLAttributeValues

Review URL: https://codereview.chromium.org/1398453005

Cr-Commit-Position: refs/heads/master@{#353712}