<commit_before>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_io_SslCertificate.h"
#include "jnc_io_SslLib.h"

namespace jnc {
namespace io {

//..............................................................................

JNC_DEFINE_TYPE(
	SslCertNameEntry,
	"io.SslCertNameEntry",
	g_sslLibGuid,
	SslLibCacheSlot_SslCertNameEntry
	)

JNC_BEGIN_TYPE_FUNCTION_MAP(SslCertNameEntry)
JNC_END_TYPE_FUNCTION_MAP()

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

JNC_DEFINE_OPAQUE_CLASS_TYPE(
	SslCertName,
	"io.SslCertName",
	g_sslLibGuid,
	SslLibCacheSlot_SslCertName,
	SslCertName,
	&SslCertName::markOpaqueGcRoots
	)

JNC_BEGIN_TYPE_FUNCTION_MAP(SslCertName)
	JNC_MAP_CONSTRUCTOR(&jnc::construct<SslCertName>)
	JNC_MAP_DESTRUCTOR(&jnc::destruct<SslCertName>)

	JNC_MAP_CONST_PROPERTY("m_entryTable", &SslCertName::getEntryTable)
	JNC_MAP_CONST_PROPERTY("m_oneLine", &SslCertName::getOneLine)

	JNC_MAP_FUNCTION("findEntry", &SslCertName::findEntry)
JNC_END_TYPE_FUNCTION_MAP()

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

JNC_DEFINE_OPAQUE_CLASS_TYPE(
	SslCertificate,
	"io.SslCertificate",
	g_sslLibGuid,
	SslLibCacheSlot_SslCertificate,
	SslCertificate,
	&SslCertificate::markOpaqueGcRoots
	)

JNC_BEGIN_TYPE_FUNCTION_MAP(SslCertificate)
	JNC_MAP_CONSTRUCTOR(&jnc::construct<SslCertificate>)
	JNC_MAP_DESTRUCTOR(&jnc::destruct<SslCertificate>)

	JNC_MAP_CONST_PROPERTY("m_serialNumber", &SslCertificate::getSerialNumber)
	JNC_MAP_CONST_PROPERTY("m_validFromDate", &SslCertificate::getValidFromDate)
	JNC_MAP_CONST_PROPERTY("m_validToDate", &SslCertificate::getValidToDate)
	JNC_MAP_CONST_PROPERTY("m_subject", &SslCertificate::getSubject)
	JNC_MAP_CONST_PROPERTY("m_issuer", &SslCertificate::getIssuer)

	JNC_MAP_FUNCTION("encode", &SslCertificate::encode)
	JNC_MAP_FUNCTION("decode", &SslCertificate::decode)
	JNC_MAP_FUNCTION("load", &SslCertificate::load)
	JNC_MAP_FUNCTION("save", &SslCertificate::save)
JNC_END_TYPE_FUNCTION_MAP()

//..............................................................................

void
JNC_CDECL
SslCertName::markOpaqueGcRoots(jnc::GcHeap* gcHeap)
{
	size_t count = m_entryArray.getCount();
	for (size_t i = 0; i < count; i++)
		gcHeap->markDataPtr(m_entryArray[i]);

	gcHeap->markDataPtr(m_oneLinePtr);
}

DataPtr
JNC_CDECL
SslCertName::getEntryTable(
	SslCertName* self,
	size_t i
	)
{
	X509_NAME_ENTRY* entry = X509_NAME_get_entry(self->m_name, i);
	if (!entry)
		return g_nullDataPtr;

	size_t count = self->m_entryArray.getCount();
	if (i < count && self->m_entryArray[i].m_p)
		return self->m_entryArray[i];

	if (i >= count)
		self->m_entryArray.setCount(i + 1);

	self->m_entryArray[i] = createEntry(entry);
	return self->m_entryArray[i];
}

DataPtr
JNC_CDECL
SslCertName::getOneLine(SslCertName* self)
{
	if (self->m_oneLinePtr.m_p)
		return self->m_oneLinePtr;

    char* p = X509_NAME_oneline(self->m_name, NULL, 0);
	self->m_oneLinePtr = strDup(p);
	OPENSSL_free(p);

	return self->m_oneLinePtr;
}

DataPtr
JNC_CDECL
SslCertName::findEntry(
	SslCertName* self,
	int nid
	)
{
	int i = X509_NAME_get_index_by_NID(self->m_name, nid, -1);
	return i >= 0 ? getEntryTable(self, i) : g_nullDataPtr;
}

DataPtr
SslCertName::createEntry(X509_NAME_ENTRY* srcEntry)
{
	ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(srcEntry);
	ASN1_STRING* value = X509_NAME_ENTRY_get_data(srcEntry);

	Runtime* runtime = getCurrentThreadRuntime();
	runtime->getGcHeap()->enterNoCollectRegion();

	DataPtr ptr = createData<SslCertNameEntry>(runtime);
	SslCertNameEntry* dstEntry = (SslCertNameEntry*)ptr.m_p;
	dstEntry->m_nid = OBJ_obj2nid(object);
	dstEntry->m_namePtr = strDup(cry::getAsn1ObjectString(object));
	dstEntry->m_valuePtr = strDup(cry::getAsn1StringString(value));

	runtime->getGcHeap()->leaveNoCollectRegion(false);
	return ptr;
}

//..............................................................................

SslCertificate*
SslCertificate::create(X509* cert)
{
	Runtime* runtime = getCurrentThreadRuntime();
	SslCertificate* self = createClass<SslCertificate>(runtime);
	self->m_cert = cert;
	return self;
}

void
JNC_CDECL
SslCertificate::markOpaqueGcRoots(jnc::GcHeap* gcHeap)
{
	gcHeap->markDataPtr(m_serialNumberPtr);
	gcHeap->markClassPtr(m_subject);
	gcHeap->markClassPtr(m_issuer);
}

DataPtr
JNC_CDECL
SslCertificate::getSerialNumber(SslCertificate* self)
{
	if (self->m_serialNumberPtr.m_p)
		return self->m_serialNumberPtr;
<commit_msg>[jnc_io_ssl] critical bugfix: SslCertName::getEntryTable should extend the entry array with setCountZeroConstruct (potential unintialized pointer access, otherwise)<commit_after>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_io_SslCertificate.h"
#include "jnc_io_SslLib.h"

namespace jnc {
namespace io {

//..............................................................................

JNC_DEFINE_TYPE(
	SslCertNameEntry,
	"io.SslCertNameEntry",
	g_sslLibGuid,
	SslLibCacheSlot_SslCertNameEntry
	)

JNC_BEGIN_TYPE_FUNCTION_MAP(SslCertNameEntry)
JNC_END_TYPE_FUNCTION_MAP()

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

JNC_DEFINE_OPAQUE_CLASS_TYPE(
	SslCertName,
	"io.SslCertName",
	g_sslLibGuid,
	SslLibCacheSlot_SslCertName,
	SslCertName,
	&SslCertName::markOpaqueGcRoots
	)

JNC_BEGIN_TYPE_FUNCTION_MAP(SslCertName)
	JNC_MAP_CONSTRUCTOR(&jnc::construct<SslCertName>)
	JNC_MAP_DESTRUCTOR(&jnc::destruct<SslCertName>)

	JNC_MAP_CONST_PROPERTY("m_entryTable", &SslCertName::getEntryTable)
	JNC_MAP_CONST_PROPERTY("m_oneLine", &SslCertName::getOneLine)

	JNC_MAP_FUNCTION("findEntry", &SslCertName::findEntry)
JNC_END_TYPE_FUNCTION_MAP()

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

JNC_DEFINE_OPAQUE_CLASS_TYPE(
	SslCertificate,
	"io.SslCertificate",
	g_sslLibGuid,
	SslLibCacheSlot_SslCertificate,
	SslCertificate,
	&SslCertificate::markOpaqueGcRoots
	)

JNC_BEGIN_TYPE_FUNCTION_MAP(SslCertificate)
	JNC_MAP_CONSTRUCTOR(&jnc::construct<SslCertificate>)
	JNC_MAP_DESTRUCTOR(&jnc::destruct<SslCertificate>)

	JNC_MAP_CONST_PROPERTY("m_serialNumber", &SslCertificate::getSerialNumber)
	JNC_MAP_CONST_PROPERTY("m_validFromDate", &SslCertificate::getValidFromDate)
	JNC_MAP_CONST_PROPERTY("m_validToDate", &SslCertificate::getValidToDate)
	JNC_MAP_CONST_PROPERTY("m_subject", &SslCertificate::getSubject)
	JNC_MAP_CONST_PROPERTY("m_issuer", &SslCertificate::getIssuer)

	JNC_MAP_FUNCTION("encode", &SslCertificate::encode)
	JNC_MAP_FUNCTION("decode", &SslCertificate::decode)
	JNC_MAP_FUNCTION("load", &SslCertificate::load)
	JNC_MAP_FUNCTION("save", &SslCertificate::save)
JNC_END_TYPE_FUNCTION_MAP()

//..............................................................................

void
JNC_CDECL
SslCertName::markOpaqueGcRoots(jnc::GcHeap* gcHeap)
{
	size_t count = m_entryArray.getCount();
	for (size_t i = 0; i < count; i++)
		gcHeap->markDataPtr(m_entryArray[i]);

	gcHeap->markDataPtr(m_oneLinePtr);
}

DataPtr
JNC_CDECL
SslCertName::getEntryTable(
	SslCertName* self,
	size_t i
	)
{
	X509_NAME_ENTRY* entry = X509_NAME_get_entry(self->m_name, i);
	if (!entry)
		return g_nullDataPtr;

	size_t count = self->m_entryArray.getCount();
	if (i < count && self->m_entryArray[i].m_p)
		return self->m_entryArray[i];

	if (i >= count)
		self->m_entryArray.setCountZeroConstruct(i + 1);

	self->m_entryArray[i] = createEntry(entry);
	return self->m_entryArray[i];
}

DataPtr
JNC_CDECL
SslCertName::getOneLine(SslCertName* self)
{
	if (self->m_oneLinePtr.m_p)
		return self->m_oneLinePtr;

    char* p = X509_NAME_oneline(self->m_name, NULL, 0);
	self->m_oneLinePtr = strDup(p);
	OPENSSL_free(p);

	return self->m_oneLinePtr;
}

DataPtr
JNC_CDECL
SslCertName::findEntry(
	SslCertName* self,
	int nid
	)
{
	int i = X509_NAME_get_index_by_NID(self->m_name, nid, -1);
	return i >= 0 ? getEntryTable(self, i) : g_nullDataPtr;
}

DataPtr
SslCertName::createEntry(X509_NAME_ENTRY* srcEntry)
{
	ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(srcEntry);
	ASN1_STRING* value = X509_NAME_ENTRY_get_data(srcEntry);

	Runtime* runtime = getCurrentThreadRuntime();
	NoCollectRegion noCollectRegion(runtime, false);

	DataPtr ptr = createData<SslCertNameEntry>(runtime);
	SslCertNameEntry* dstEntry = (SslCertNameEntry*)ptr.m_p;
	dstEntry->m_nid = OBJ_obj2nid(object);
	dstEntry->m_namePtr = strDup(cry::getAsn1ObjectString(object));
	dstEntry->m_valuePtr = strDup(cry::getAsn1StringString(value));
	return ptr;
}

//..............................................................................

SslCertificate*
SslCertificate::create(X509* cert)
{
	Runtime* runtime = getCurrentThreadRuntime();
	SslCertificate* self = createClass<SslCertificate>(runtime);
	self->m_cert = cert;
	return self;
}

void
JNC_CDECL
SslCertificate::markOpaqueGcRoots(jnc::GcHeap* gcHeap)
{
	gcHeap->markDataPtr(m_serialNumberPtr);
	gcHeap->markClassPtr(m_subject);
	gcHeap->markClassPtr(m_issuer);
}

DataPtr
JNC_CDECL
SslCertificate::getSerialNumber(SslCertificate* self)
{
	if (self->m_serialNumberPtr.m_p)
		return self->m_serialNumberPtr;

{'fraction_non_alphanumeric': 0.20271639975674033, 'fraction_numerical': 0.006892357591729171, 'mean_word_length': 3.6345702207609207, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6338546', 'n_tokens_mistral': 3763, 'n_tokens_neox': 3696, 'n_words': 488}